Front page | perl.perl5.porters |
Postings from July 2009
[perl #67838] lvalue substr leaks memory? (was: lvalue substr keeping lexical alive)
From:
Bram via RT
Date:
July 24, 2009 03:49
Subject:
[perl #67838] lvalue substr leaks memory? (was: lvalue substr keeping lexical alive)
Message ID:
rt-3.6.HEAD-2466-1248430216-1812.67838-15-0@perl.org
On Thu Jul 23 17:19:15 2009, kryde wrote:
> The program foo.pl below prints
>
> SCALAR(0x874b2c0)
>
> where I hoped it would print undef, ie. the lexical scalar $str would
> be
> garbage collected on going out of scope. undef is what I get without
> the lvalue substr() assignment, or with a 4-arg substr call.
>
> Some digging around suggests the scratchpad array in foo() holds a
> reference to the $str scalar if an lvalue substr is used this way. I
> don't know if that's a bug, a feature, or an unavoidable side-effect
> of
> the implementation.
>
> If a feature or unavoidable then take this report as a wish for
> something in the docs on the subject, as even perlguts seems very
thin
> on anything about lvalue scalars.
>
>
lvalue substr seems to leak...
Test case:
#!/usr/bin/perl -l
use strict;
use warnings;
my $str = 'Hello World';
print "before: " . Internals::SvREFCNT($str);
substr($str,0,1) = 'x';
print "after (1): " . Internals::SvREFCNT($str);
substr($str,0,1) = 'x';
print "after (2): " . Internals::SvREFCNT($str);
for (3, 4) {
print "before ($_) (loop): " . Internals::SvREFCNT($str);
substr($str,0,1) = 'x';
print "after ($_) (loop): " . Internals::SvREFCNT($str);
}
__END__
Output (with blead):
before: 1
after (1): 2
after (2): 3
before (3) (loop): 3
after (3) (loop): 4
before (4) (loop): 4
after (4) (loop): 4
(perl-5.6.0 (tested with Devel::Peek), perl-5.8.0 and everything in
between behaves the same as blead)
I'm guessing this is due to:
LvTYPE(TARG) = 'x';
if (LvTARG(TARG) != sv) {
if (LvTARG(TARG))
SvREFCNT_dec(LvTARG(TARG));
LvTARG(TARG) = SvREFCNT_inc_simple(sv);
}
in pp_substr.
Looking at the blame log this seems to be added in:
http://perl5.git.perl.org/perl.git/blobdiff/
15e73149a8419f18d739227762eab108524cec56..ae389c8a29b487f4434c465442dfb611507a4a38:/
pp.c
[core language changes]
Title: "5.004_04m5t1: Fix dangling references in LVs", "Fix dangling
references in LVs"
Msg-ID: <199804010541.AAA32615@Orb.Nashua.NH.US>,
<19980422164037.D29222@perl.org>
Files: embed.h keywords.h opcode.h perl.h proto.h doop.c global.sym
mg.c
pp.c sv.c
Title: "Fix SvGMAGIC typo in change 904"
Files: doop.c
p4raw-id: //depot/maint-5.004/perl@906
Unfortunally no tests are added in that change :(
This change also indicates that the same happens for vec() and pos():
#!/usr/bin/perl -l
use strict;
use warnings;
my $str = 'Hello World';
print "before: " . Internals::SvREFCNT($str);
vec($str,0,1) = 0;
print "after (1): " . Internals::SvREFCNT($str);
vec($str,0,1) = 0;
print "after (2): " . Internals::SvREFCNT($str);
for (3, 4) {
print "before ($_) (loop): " . Internals::SvREFCNT($str);
vec($str,0,1) = 0;
print "after ($_) (loop): " . Internals::SvREFCNT($str);
}
__END__
before: 1
after (1): 2
after (2): 3
before (3) (loop): 3
after (3) (loop): 4
before (4) (loop): 4
after (4) (loop): 4
#!/usr/bin/perl -l
use strict;
use warnings;
my $str = 'Hello World';
print "before: " . Internals::SvREFCNT($str);
pos($str) = 0;
print "after (1): " . Internals::SvREFCNT($str);
pos($str) = 0;
print "after (2): " . Internals::SvREFCNT($str);
for (3, 4) {
print "before ($_) (loop): " . Internals::SvREFCNT($str);
pos($str) = 0;
print "after ($_) (loop): " . Internals::SvREFCNT($str);
}
__END__
before: 1
after (1): 2
after (2): 3
before (3) (loop): 3
after (3) (loop): 4
before (4) (loop): 4
after (4) (loop): 4
Anyone remembers the reason why this is/was nessesary?
(I haven't tested yet what happens when the refcount isn't increased)
Best regards,
Bram
-
[perl #67838] lvalue substr leaks memory? (was: lvalue substr keeping lexical alive)
by Bram via RT