Skip Menu |
Report information
Id: 18581
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: khkramer [at] allafrica.com
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: low
Type: unknown
Perl Version: 5.8.0
Fixed In: (no value)

Attachments
0001-Demonstrate-timely-destruction-of-object.patch



Date: 21 Nov 2002 22:41:28 -0000
From: khkramer [...] allafrica.com
To: perlbug [...] perl.org
Subject: memory leak: if($foo++){} and = overloading
Download (untitled) / with headers
text/plain 5.4k
From: kwindla@allafrica.com Hi, There appears to be a scoping problem that certain kinds of operator overloading can trigger, leading to a memory leak. The bug shows up in both 5.8.0 and 5.6.1. The constructions: while ( $foo++ ) {} if ( $foo++ ) {} lead to $foo's reference count being high by one, if $foo is an object that returns a reference to itself in its copy constructor. This bug is easily reproduced -- I have attached a test case below. I have not succeeded in finding a work-around. Using WeakRef, writing XS code by hand to mortalize the reference, and various attempts to take/make copies of the object and return those, all run into dead ends. Just to clarify, I've carefully read all the information I can find on operator overloading and the copy constructor (Camel book pages 357-358, perldoc overload), as well as perlguts and perlapi. I believe that I understand how copy constructor overloading works, and why -- the bug is not (as I see it) in the copy-constructor overloading itself, but in the interaction between the scoping of while()/if() and the overload. Other constructions that trigger the copy-constructor, but that don't have the same form as while(){} and if(){}, work fine with my test-case, such as: my $copy = $foo; $foo++; This bug, while admittedly in a very obscure corner of Perl, turns out to be a big problem if one is writing iterator-style objects that need to be used inside long-running processes (such as a web server). That's what I'm doing, and that's how I found this bug. I apologize for not having a patch. I've gotten lost in the perl 5.8.0 source, and am not having much luck finding my way to the appropriate sections. With sincere thanks, Kwindla ---- package Toy_Iterator; use overload '""' => sub { $_[0] }, bool => sub { ! $_[0]->done_p() }, '++' => \&inc, '=' => sub { $_[0] }, ; sub new { my ( $class, $arg ) = @_; my $self = {}; bless $self, $class; $self->set ( $arg ); return $self; } sub set { $_[0]->{_i} = $_[1] } sub get { return $_[0]->{_i} } sub inc { ++$_[0]->{_i} } sub done_p { $_[0]->{_i} > 5 } sub DESTROY { print "Destroying $_[0]\n" } package main; use Devel::Peek; my $a = Toy_Iterator->new ( 2 ); ## # The while/++ idiom causes there to be a leaked reference to the # object. # while ( $a++ ) { print "$a -> " . $a->get() . "\n"; } ## # On the other hand, it's not a problem with the copy constructor # *per-se*, because this code does not cause the leak # # my $copy = $a; # $copy++; # undef $copy; print "\n"; Dump $a; print "\n"; print "undef'ing \$a...\n"; undef $a; print "---- script finished (should have already gc'ed) ---\n"; --- Flags: category=core severity=medium --- Site configuration information for perl v5.8.0: Configured by khkramer at Thu Nov 14 13:37:07 EST 2002. Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: Platform: osname=linux, osvers=2.4.7-10, archname=i686-linux uname='linux khk 2.4.7-10 #1 thu sep 6 16:46:36 edt 2001 i686 unknown ' config_args='-de -Dprefix=/usr -Dotherlibdirs=/allafrica/perllib:/usr/lib/perl5/site_perl/5.6.1/i386-linux:/usr/lib/perl5/vendor_perl/5.6.1:/usr/lib/perl5/vendor_perl/5.6.1/i386-linux:/usr/lib/perl5:/usr/lib/perl5/5.6.0' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', optimize='-O2', cppflags='-fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' ccversion='', gccversion='2.96 20000731 (Red Hat Linux 7.2 2.96-108.7.2)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldl -lm -lc -lcrypt -lutil perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil libc=/lib/libc-2.2.4.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.2.4' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: --- @INC for perl v5.8.0: /usr/lib/perl5/5.8.0/i686-linux /usr/lib/perl5/5.8.0 /usr/lib/perl5/site_perl/5.8.0/i686-linux /usr/lib/perl5/site_perl/5.8.0 /usr/lib/perl5/site_perl/5.6.1 /usr/lib/perl5/site_perl/5.6.0 /usr/lib/perl5/site_perl /allafrica/perllib /usr/lib/perl5/site_perl/5.6.1/i386-linux /usr/lib/perl5/vendor_perl/5.6.1 /usr/lib/perl5/vendor_perl/5.6.1/i386-linux /usr/lib/perl5/5.8.0/i686-linux /usr/lib/perl5/5.8.0 /usr/lib/perl5/5.6.1 /usr/lib/perl5/5.6.0 /usr/lib/perl5 /usr/lib/perl5/5.6.0 . --- Environment for perl v5.8.0: HOME=/u/khkramer LANG=en_US LANGUAGE (unset) LC_COLLATE=POSIX LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/u/khkramer/bin:/allafrica/bin PERL_BADLANG (unset) SHELL=/bin/bash
Date: Thu, 21 Nov 2002 22:49:13 -0500
From: Benjamin Goldberg <goldbb2 [...] earthlink.net>
To: perl5-porters [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 572b
khkramer@allafrica.com (via RT) wrote: [snip] Show quoted text
> package Toy_Iterator; > > use overload > '""' => sub { $_[0] }, > bool => sub { ! $_[0]->done_p() }, > '++' => \&inc, > '=' => sub { $_[0] }, > ;
Your copy constructor (the '=' operator) doesn't appear to do anything. Could this be the source of your problems? (Try replacing that line with: '=' => sub { ref( $_[0] )->new( $_[0]->get ) }, and perhaps your bug will go away. [Untested].) -- my $n = 2; print +(split //, 'e,4c3H r ktulrnsJ2tPaeh' ...."\n1oa! er")[map $n = ($n * 24 + 30) % 31, (42) x 26]
From: Kwindla Hultman Kramer <kwindla [...] allafrica.com>
Date: Fri, 22 Nov 2002 11:42:50 -0500
To: perlbug [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 1.7k
Benjamin Goldberg (via RT) writes: Show quoted text
> khkramer@allafrica.com (via RT) wrote: > [snip]
> > package Toy_Iterator; > > > > use overload > > '""' => sub { $_[0] }, > > bool => sub { ! $_[0]->done_p() }, > > '++' => \&inc, > > '=' => sub { $_[0] }, > > ;
> > Your copy constructor (the '=' operator) doesn't appear to do anything. > > Could this be the source of your problems? > > (Try replacing that line with: > '=' => sub { ref( $_[0] )->new( $_[0]->get ) }, > and perhaps your bug will go away. [Untested].) >
Well, returning oneself in the overloaded copy constructor works flawlessly in all cases except: while ($foo++) {} and if ($foo++) In particular: while (++$foo) {} # doesn't trigger copy constructor, and my $bar = $foo; $foo++; # triggers copy constructor, ref counts stay correct are fine. The problem -- as far as I can tell -- is not in the copy constructor that I've written but in the reference counting logic for the above two cases. And I'm specifically trying to show what happens in the case of a copy constructor that shouldn't "do anything" (so to speak). The code you suggest would be a possible workaround for lots of situations in which this bug is encountered. But some objects can't (or shouldn't) be copied. For example, an object might have lots of state, and a copy operation would be prohibitively slow. Or an object might have open network or database handles that, because of the architecture on the other end of the pipe, can't be closed and re-opened. My understanding of copy constructor overloading is that an actual "copy" operation is optional -- an important component of DWIM in many situations, but not something that the Perl interpreter ever forces you to do. Kwin
To: perl5-porters [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
From: hv [...] crypt.org
Date: Mon, 23 Dec 2002 04:15:58 +0000
RT-Send-Cc:
Download (untitled) / with headers
text/plain 2.1k
"khkramer@allafrica.com (via RT)" <perlbug@perl.org> wrote: :There appears to be a scoping problem that certain kinds of operator :overloading can trigger, leading to a memory leak. The bug shows up in :both 5.8.0 and 5.6.1. : :The constructions: : : while ( $foo++ ) {} : if ( $foo++ ) {} : :lead to $foo's reference count being high by one, if $foo is an object :that returns a reference to itself in its copy constructor. There is a bug here, but the while (or if) is a red herring; stripping down the test case some more gets me to: use overload '++' => sub { $_[0] }, '=' => sub { $_[0] }; sub DESTROY { print "Destroying $_[0]\n" } { my $a = bless {}, main; my $b = $a++; } print "---- script finished (should have already gc'ed) ---\n"; .. which shows that the object is destroyed late. If the 'my $b = $a++' is removed, the object is destroyed as expected at the end of the block. Devel::Peek shows that after that line, the refcount of the referent has jumped to 3 rather than 2 as expected. It goes something like this: - pp_postinc first does the assign, via the overloaded '='. The refcount goes to 2 as expected. - pp_postinc then calls sv_inc, which spots overloading and asks amagic_call to do the work - amagic_call works out what it needs to do, and then spots that it should copy (RvDEEPCP) the argument. Since the refcount of the referent is now 2, this macro drops the refcount to 1 and calls the overloaded '=' once more to do the copy - we're now recursing into amagic_call, which sets up a scope and calls the '=' sub; on return from that sub, as you'd expect, the refcount has once more gone up to 2 - .. but just before returning, amagic_call ups the refcount again: } else if (method==copy_amg) { [...] return SvREFCNT_inc(SvRV(res)); .. which makes 3. I've no idea why it does that, either (but removing that SvREFCNT_inc causes lib/overload.t to SEGV). Now I'm not sure how we handle the refcounting of return values; as I understand it the refcount should be temporarily increased (to survive the scope cleanup) but I'm not sure when it should be decreased again. That I think is what is not happening in this case. Hugo
To: Tels <perl_dummy [...] bloodgate.com>
Cc: perl5-porters [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
From: hv [...] crypt.org
Date: Tue, 24 Dec 2002 11:45:30 +0000
RT-Send-Cc:
Download (untitled) / with headers
text/plain 679b
Tels <perl_dummy@bloodgate.com> wrote: :"khkramer@allafrica.com (via RT)" <perlbug@perl.org> wrote: :>lead to $foo's reference count being high by one, if $foo is an object :>that returns a reference to itself in its copy constructor. : :Uh, but isn't a copy constructor supposed to copy something, instead of :merely returning the same thing? How should that supposed to work with a :"defect" copy constructor? : :*puzzled* I couldn't see anything in the docs to state or imply that returning the thing itself should be illegal, and I can see no reason for it to be so. And if it should be illegal, we should make it an error rather than silently doing the wrong thing. Hugo
From: Kwindla Hultman Kramer <kwindla [...] allafrica.com>
Date: Thu, 26 Dec 2002 14:58:02 -0500
To: perlbug-followup [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 1.4k
Hugo van der Sanden (via RT) writes: Show quoted text
> Tels <perl_dummy@bloodgate.com> wrote: > :"khkramer@allafrica.com (via RT)" <perlbug@perl.org> wrote: > :>lead to $foo's reference count being high by one, if $foo is an object > :>that returns a reference to itself in its copy constructor. > : > :Uh, but isn't a copy constructor supposed to copy something, instead of > :merely returning the same thing? How should that supposed to work with a > :"defect" copy constructor? > : > :*puzzled* > > I couldn't see anything in the docs to state or imply that returning the > thing itself should be illegal, and I can see no reason for it to be so. > And if it should be illegal, we should make it an error rather than > silently doing the wrong thing. >
In addition, if we "force" the copy constructor to actually copy something, a whole raft of common and useful approaches become tortuous and inefficient. I'm thinking particularly of while ( $foo++ ) {} # and if ( $foo++ ) {} constructions on iterator-like $foos. Thanks to Hugo for further stripping down the test-case to demonstrate that the problem isn't while- and if-centric (and mea culpa for not doing so myself), but my problems that led to submitting the bug report were exactly the above. If I have to actually copy my $foos in order to use the post-increment operator -- which include lots of stored state and (usually) a live database handle or two -- I'll have to stop using overloading. Kwin
Date: Fri, 27 Dec 2002 15:33:49 -0500
From: Benjamin Goldberg <goldbb2 [...] earthlink.net>
To: Kwindla Hultman Kramer <kwindla [...] allafrica.com>, p5p <perl5-porters [...] perl.org>
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 2.3k
Kwindla Hultman Kramer wrote: Show quoted text
> > Hugo van der Sanden (via RT) writes:
> > Tels <perl_dummy@bloodgate.com> wrote: > > :"khkramer@allafrica.com (via RT)" <perlbug@perl.org> wrote: > > :>lead to $foo's reference count being high by one, if $foo is an > > :>object that returns a reference to itself in its copy > > :>constructor. > > : > > :Uh, but isn't a copy constructor supposed to copy something, > > :instead of merely returning the same thing? How should that > > :supposed to work with a "defect" copy constructor? > > : > > :*puzzled* > > > > I couldn't see anything in the docs to state or imply that > > returning the thing itself should be illegal, and I can see no > > reason for it to be so. > > And if it should be illegal, we should make it an error rather than > > silently doing the wrong thing. > >
> > In addition, if we "force" the copy constructor to actually copy > something, a whole raft of common and useful approaches become > tortuous and inefficient. I'm thinking particularly of > > while ( $foo++ ) {} # and > if ( $foo++ ) {} > > constructions on iterator-like $foos.
If your copy-constructor doesn't make a copy, but just returns $self, and your post-increment operator is similar, then aren't the above (under the old semantics) exactly the same as: while ( ++$foo ) {} # and if ( ++$foo ) {} ? Show quoted text
> Thanks to Hugo for further stripping down the test-case to demonstrate > that the problem isn't while- and if-centric (and mea culpa for not > doing so myself), but my problems that led to submitting the bug > report were exactly the above. If I have to actually copy my $foos in > order to use the post-increment operator -- which include lots of > stored state and (usually) a live database handle or two -- I'll have > to stop using overloading.
Or else switch from using the post-increment operator to using the pre-increment operator. Hmm.. if we *do* make using a defective copy-constructor into a death, then might I suggest that the error message be something like: 'Can't do $val++ with bad copy-constructor, use ++$val instead.' ... assuming that we can easily determine which operation was called that needed to call the copy-constructor. -- $..='(?:(?{local$^C=$^C|'.(1<<$_).'})|)'for+a..4; $..='(?{print+substr"\n !,$^C,1 if $^C<26})(?!)'; $.=~s'!'haktrsreltanPJ,r coeueh"';BEGIN{${"\cH"} |=(1<<21)}""=~$.;qw(Just another Perl hacker,\n);
From: Kwindla Hultman Kramer <kwindla [...] allafrica.com>
Date: Fri, 27 Dec 2002 15:42:15 -0500
To: perlbug-followup [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 1.2k
Benjamin Goldberg (via RT) writes: Show quoted text
> If your copy-constructor doesn't make a copy, but just returns $self, > and your post-increment operator is similar, then aren't the above > (under the old semantics) exactly the same as: > > while ( ++$foo ) {} # and > if ( ++$foo ) {} >
[ snip ] Show quoted text
> Or else switch from using the post-increment operator to using the > pre-increment operator. >
You're right that there's no operational difference between using pre- and post-increment operators in my examples. But, I stumbled on this bug after adding operator overloading to an often-used chunk of a library I maintain, and the memory-leak wasn't immediately obvious. There's now lots of code "in the wild" that uses the post-increment version. This doesn't have catastrophic effects -- there's some memory leakage and the garbage collector often has difficulty doing a graceful global destruction (when a process exits). But no big deal. The library documentation now explains what's going on -- $foo++ is deprecated, yadda yadda -- but I can't completely remove the post-increment stuff without breaking existing code. And it would be nice not to have to explain (or remember) that ++$foo is allowed but $foo++ isn't! Yours, Kwin
From: Kwindla Hultman Kramer <kwindla [...] allafrica.com>
Date: Sat, 28 Dec 2002 12:53:33 -0500
To: Tels <perl_dummy [...] bloodgate.com>
Cc: perlbug-followup [...] perl.org, goldbb2 [...] earthlink.net
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 2.5k
Tels writes: Show quoted text
> I still think that overloading with a copy operator that does not copy is > "broken" code. But more for the reason that it will bite you later on, like: > > $x = $y; > $x += 1; > > Now you also modified $y, which might come quite unsuspected. So, > preferable you could change you copy constructor :)) >
But that's only one way of looking at what $x = $y; means. You're right, that often the '=' statement serves to put a "distinct" copy of the value of $y into the variable $x. But in the heavily object-oriented code that I spend most of my time writing, the programmer's intent is usually quite different: to assign to $x a copy of the reference that $y holds. Note that in Perl, refererences are just another kind of value, and the second "intent" is what Perl *always* does by default if $y holds any kind of reference. So it seems to me that making copy constructors that return "self" illegal is actually breaking the language. The behavior that programmers expect from the core language becomes impossible to implement for any classes that use (a certain configuration) of operator overloading. I think that Perl's wonderfully-flexible reference-munging facilities are causing some confusion here. I'm maintaining a library of around 15,000 lines of rigidly object-oriented code -- all of the OO features of which are built transparently and gracefully on top of Perl's basic "bless this reference" capability. Everything just works -- end-users (programmers, in this case, since we're talking about a library) never need to think about how the OO stuff is implemented, they just use it. But when necessary, I can dig underneath the OO abstraction to do low-level operations on namespaces, classes, syntax, serialization, etc. The only place this breaks is in the operator overloading, where the "copy constructor" feature doesn't let you do what the core language would do if left to its own devices. To wind back around to $x and $y, in much of my code $y->set ( 42 ); $x = $y; $x++; both $x->get() and $y->get() had *better* return 43 after the above statements, or programmers are going to be very unhappy. This is a contrived example, and taken out of context I can see why it looks funny. But think about iterators, or singletons that control access to shared resources, or objects that require lots of computation to initialize but are thereafter shared by lots of bits of a system -- all these cases require that the above behavior be the norm. Hope this makes my perspective little clearer, Kwin
From: sthoenna [...] efn.org (Yitzchak Scott-Thoennes)
To: perl5-porters [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
Date: Sun, 29 Dec 2002 12:58:15 -0800
Cc: perl_dummy [...] bloodgate.com
RT-Send-Cc:
Download (untitled) / with headers
text/plain 720b
On Sat, 28 Dec 2002 02:45:52 +0100 (CET), perl_dummy@bloodgate.com wrote: Show quoted text
> if ($foo++) > { > ... > } > >It should do: > >* check that $foo is true, then increment it. > >But for some reason it does: > >* copy $foo, increment the original, then check the copy for beeing true, > then throw away the copy (or something similiar) > >Note that there is a needless copy here.
I don't think this can easily change, since internally perl only differentiates between void, scalar, and list context. There is no easy way for the postinc code to check if it is called in an actual scalar context (in which case, the copy is needed) or boolean context (in which case the copy is not needed).
Date: Mon, 30 Dec 2002 17:37:16 +0100
From: Rafael Garcia-Suarez <rgarciasuarez [...] free.fr>
To: Tels <perl_dummy [...] bloodgate.com>
Cc: sthoenna [...] efn.org, perl5-porters [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
RT-Send-Cc:
Download (untitled) / with headers
text/plain 666b
Tels <perl_dummy@bloodgate.com> wrote: Show quoted text
> > > > I don't think this can easily change, since internally perl only > > differentiates between void, scalar, and list context. There is no > > easy way for the postinc code to check if it is called in an actual > > scalar context (in which case, the copy is needed) or boolean context > > (in which case the copy is not needed).
> > You may be right. How hard would it be to introduce a boolean context?
There is no free bit left in op_flags, but in theory, the optimizer could label ops that semantically provide a boolean context as 'gimme-bool'. Or at least I imagine it's possible. (see Want.pm for inspiration.)
To: Rafael Garcia-Suarez <rgarciasuarez [...] free.fr>
Cc: perl5-porters [...] perl.org
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
From: hv [...] crypt.org
Date: Tue, 31 Dec 2002 02:36:04 +0000
RT-Send-Cc:
Download (untitled) / with headers
text/plain 998b
Rafael Garcia-Suarez <rgarciasuarez@free.fr> wrote: :Tels <perl_dummy@bloodgate.com> wrote: :> > :> > I don't think this can easily change, since internally perl only :> > differentiates between void, scalar, and list context. There is no :> > easy way for the postinc code to check if it is called in an actual :> > scalar context (in which case, the copy is needed) or boolean context :> > (in which case the copy is not needed). :> :> You may be right. How hard would it be to introduce a boolean context? : :There is no free bit left in op_flags, but in theory, the optimizer could label :ops that semantically provide a boolean context as 'gimme-bool'. Or at least :I imagine it's possible. (see Want.pm for inspiration.) I think this would be a rather large change, and I'm not convinced this edge-case is important enough to warrant it. For this particular case, you can get avoid the copy with a bit of extra effort: if (!$foo) { ++$foo; } else { ++$foo; ... } Hugo
Download (untitled) / with headers
text/plain 199b
I changed this from ‘stalled’ to ‘open’, because I think ‘stalled’ usually means there is not enough information to reproduce the bug. And someone may want to revisit this bug some day.
To: perl5-porters [...] perl.org
Date: Tue, 16 Jan 2018 21:32:45 +0000
From: Zefram <zefram [...] fysh.org>
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
Download (untitled) / with headers
text/plain 119b
This was fixed by commit 7dcb9b98df566764105b8c15283b393878a1788e in Perl 5.13.5. This ticket can be closed. -zefram
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 442b
On Tue, 16 Jan 2018 21:32:58 GMT, zefram@fysh.org wrote: Show quoted text
> This was fixed by commit 7dcb9b98df566764105b8c15283b393878a1788e in > Perl 5.13.5. This ticket can be closed. > > -zefram
But I can hear Father C saying, "What about a test?" Please review the attached. (I'm not very familiar with 'fresh_perl_is' so I suspect both the test and the commit message could be improved.) Thank you very much. -- James E Keenan (jkeenan@cpan.org)
Subject: 0001-Demonstrate-timely-destruction-of-object.patch
From 9422dbd7fd7a3c2aaa1fcb230f0229d70c203eb2 Mon Sep 17 00:00:00 2001 From: James E Keenan <jkeenan@cpan.org> Date: Tue, 16 Jan 2018 19:21:53 -0500 Subject: [PATCH] Demonstrate timely destruction of object. For RT #18581 --- lib/overload.t | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/overload.t b/lib/overload.t index 2afa6cf..f4ce103 100644 --- a/lib/overload.t +++ b/lib/overload.t @@ -48,7 +48,7 @@ package main; $| = 1; BEGIN { require './test.pl'; require './charset_tools.pl' } -plan tests => 5338; +plan tests => 5339; use Scalar::Util qw(tainted); @@ -3047,3 +3047,25 @@ package RT132385 { # ditto with a mutator ::is($o .= $r1, "obj-ref1", "RT #132385 o.=r1"); } + +{ + no strict; + $msg = '---- script finished (should have already garbage-collected) ---'; + fresh_perl_is( + <<'EOF', +package RT18581; +use overload + '++' => sub { $_[0] }, + '=' => sub { $_[0] }; +sub DESTROY { print "Destroying $_[0]\n"; } +{ + my $a = bless {}, RT18581; + my $b = $a++; +} +print "---- script finished (should have already garbage-collected) ---\n"; +EOF + $msg, + {}, + 'RT 18581: timely destruction', + ); +} -- 2.7.4
From: Zefram <zefram [...] fysh.org>
Date: Wed, 17 Jan 2018 00:43:57 +0000
Subject: Re: [perl #18581] memory leak: if($foo++){} and = overloading
To: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 170b
James E Keenan via RT wrote: Show quoted text
>But I can hear Father C saying, "What about a test?"
This time the fix was intentional, and the commit that I cited added a test. -zefram


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org