develooper Front page | perl.perl5.porters | Postings from July 2001

Re: Memory corruption? Read-only $_?

From:
Gurusamy Sarathy
Date:
July 11, 2001 07:36
Subject:
Re: Memory corruption? Read-only $_?
Message ID:
200107111435.f6BEZXf06062@smtp3.ActiveState.com
On Wed, 11 Jul 2001 14:15:07 +0530, Abhijit Menon-Sen wrote in private mail:
>At 2001-06-29 05:01:56, rs@crystalflame.net wrote:
>> 
>> sub boom { open(FH, shift) or warn "$!"; while (<FH>) { }; close FH; }
>> 
>> my %files = ( 111111111 => 1 ); # changing the key changes the WEIRD error
>> 
>> my $c; local $d; use vars '$e';
>> 
>> warn 1; for $_ ( keys %files ) { boom $0 } # produces a WEIRD error
>> warn 2; for $_ ( 1, 2, 3, 4, ) { boom $0 } # change $_ to $a and it works
>> warn 3; for $b ( keys %files ) { boom $0 } # (no error) special global $b
>> warn 4; for $c ( keys %files ) { boom $0 } # (no error) my $c
>> warn 5; for $d ( keys %files ) { boom $0 } # (no error) local $d
>> warn 6; for $e ( keys %files ) { boom $0 } # (no error) global $e
>> 
>> __OUTPUT__
>> 1 at compare.pl line 9.
>> Attempt to free non-existent shared string '¨-@¨-@p' at compare.pl line 3.
>> 2 at compare.pl line 10.
>> Modification of a read-only value attempted at compare.pl line 3.
>> 
>> __END__
>> 
>> For some interesting fun, change the length of the hash key (shorter is
>> more interesting, though longer is also fun).
>> 
>> It seems to be a bug in $_ somewhere.  I have no idea.
>
>Actually, this is a red herring. It works with $_ in the code above only
>because of the implicit assign-to-$_ behaviour of "while (<FH>)". The
>following example demonstrates the problem better:
>
>    %foo = ( 12345678 => 1 );
>    sub foo {while ($x=<>) {}}
>    for $x (keys %foo) { foo }
>
>newSVpvn_share() is called on the hash key, which returns an SV with
>SvLEN = 0 (why?).

If SvLEN() is 0, that means the SV doesn't "own" the PVX pointer
and shouldn't free it.  If the PVX needs modification, the SV
should make a copy of it before modifying/reallocing it.  This
is essentially the mechanism for copy-on-write SVs in perl.

>$x is aliased to the hash key in the loop, and
>do_readline() calls sv_grow() on it (pp_hot.c:1503). Because SvLEN == 0,
>sv_grow() calls New() rather than Renew(), which is where the garbage
>string comes from (sv.c:1569).

This is the correct behavior for copy-on-write.

>I'm not sure how to fix this, because I don't know what the desired
>behaviour is. It seems to me that do_readline() shouldn't be trying to
>grow the key, so should the scalar be copied first?
>
>Do you have any suggestions?

I haven't looked closely, but it seems the SV should be "unshared"
when sv_grow() puts a New()ed SvPVX in it.

Cc-ed to p5p.  I'd suggest keeping such traffic on p5p in future,
since others besides us may be able to comment/learn.

Thanks for looking into the problem!


Sarathy
gsar@ActiveState.com



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