develooper 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




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About