Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^4: semi-panic: attempt to dup freed string?

by BrowserUk (Patriarch)
on Mar 25, 2011 at 08:31 UTC ( [id://895428]=note: print w/replies, xml ) Need Help??


in reply to Re^3: semi-panic: attempt to dup freed string?
in thread semi-panic: attempt to dup freed string?

By the way, using a string buffer to store a pointer is a waste. An IV is guaranteed to be big enough.

I think the reason people place pointers into the string buffer of the PV is to circumvent perl's overzealous CLONEing code from messing with it.

If you try RV->pointer_to_non_SV, you cannot bless the RV because perl check what is pointed at.

If you try RV->SvUV->pointer_to_nonSV, you can bless the Rv, but when CLONE gets it hands on it, it not only clones the RV and the SvUV, but because the SvUVs are aliased for SvRVs, it also assumes that the value in the SvUV is an SV* and clones that also. At least that is what seems to happen?

By going the RV->SvPV->string(containing pointer_to_non_SV), CLONE does expect the string to contain a pointer and so copies the original string value verbatim.

It is a messy roundabout route, but I don't see a viable alternative? And even that doesn't seem to work properly.

Grr. Why is none of this shit documented? Where are the people that know how this stuff works?


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
  • Comment on Re^4: semi-panic: attempt to dup freed string?

Replies are listed 'Best First'.
Re^5: semi-panic: attempt to dup freed string?
by ikegami (Patriarch) on Mar 25, 2011 at 17:32 UTC

    but because the SvUVs are aliased for SvRVs, it also assumes that the value in the SvUV is an SV* and clones that also.

    If Perl assume all UVs were really pointers to SVs, it would crash left and right. Either the scalar is a reference (ROK) or a UV (IOK + IsUV). What you describe will only happen for the former. I didn't suggest using a reference.

      If Perl assume all UVs were really pointers to SVs, it would crash left and right.

      Remember, I'm only suggesting this can happen during cloning, not normal operations. Remember that SvRVs & SvIVs used to be different types. Maybe the cloning code, written before this amalgamation, only checked for SvTYPE and has never been updated to further distinguish RVs from IV/UVs?

      Maybe you have a better explanation for this observed behaviour:

      ... package main; use threads; use Devel::Peek; my $o = O->new(); print $o; $o->set( "abcde" ); print $o->get(); print "\nthreaded\n"; async { print $o->get( ); $o->set( 12345 ); print $o->get( ); }->join; print $o->get(); __END__ C:\test>xso N:rv:000000000035E128 o:0000000003FFA818 O=SCALAR(0x3ffa818) S:rv;000000000035E248 o:0000000003C318F0 G:rv;000000000035E248 o:0000000003C318F0 old:000000000035E128 abcde threaded G:rv;0000000004258CA8 o:0000000004229090 old:0000000000000000 S:rv;0000000004258CA8 o:0000000004229090 G:rv;0000000004258CA8 o:0000000004229090 old:0000000004259920 12345 G:rv;000000000035E248 o:0000000003C318F0 old:000000000035E128 abcde

      Before the thread, I set a value into the struct, and get it back.

      Then I move into the thread, the RV gets cloned, the SvUV it points to gets cloned; but the value within the SvUV (labelled 'o:' in the printfs), also changes. And as the numeric value inside the UV (which we know is a pointer but Perl shouldn't), has also changed. It no longer points to the original struct. Hence, 'old:' no longer has a value.

      I then insert a different value into the struct, and successfully retrieve that value. I then exit the thread and, and get the value again, and lo, I get the original value set, not the one I modified inside the thread.

      No, the *only* explanation that I can come up with for that behaviour is that when the RV and UV get cloned, it also clones the thing that the UV points to; even though it shouldn't know that the numberic value in the UV is a pointer. Do you have a better explanation?

      The full code:

      #! perl -slw use strict; package O; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'xso', CLEAN_AFTER_BUILD => 0; typedef struct { SV**sv; } O; void *mem( size_t size ) { void *p; Newx( p, size, char ); return p; } SV *new( char *package ) { O *o = (O*)mem( sizeof( O ) ); SV *rv = newRV( (SV*)o ); o->sv = mem( sizeof( SV* ) ); sv_bless( rv, gv_stashpv( package, 0 ) ); SvREADONLY_on( rv ); printf( "N:rv:%p o:%p\n", rv, o ); return rv; } int set( SV *rv, SV *in ) { O *o = ( *(O**)SvUV( rv ) ) - 1; printf( "S:rv;%p o:%p\n", rv, o ); o->sv = newSVsv( in ); return 1; } SV *get( SV *rv ) { O *o = ( *(O**)SvUV( rv ) ) - 1; SV *old = newSVsv( o->sv ); SvREFCNT_inc( old ); printf( "G:rv;%p o:%p old:%p\n", rv, o, o->sv ); return old; } END_C package main; use threads; use Devel::Peek; my $o = O->new(); print $o; $o->set( "abcde" ); print $o->get(); print "\nthreaded\n"; async { print $o->get( ); $o->set( 12345 ); print $o->get( ); }->join; print $o->get();

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Then I move into the thread, the RV gets cloned, the SvUV it points to gets cloned; but the value within the SvUV (labelled 'o:' in the printfs), also changes.

        huh? The RV doesn't point to a UV. You never even create a scalar with a UV.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://895428]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-04-26 02:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found