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

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.

  • Comment on Re^5: semi-panic: attempt to dup freed string?

Replies are listed 'Best First'.
Re^6: semi-panic: attempt to dup freed string?
by BrowserUk (Patriarch) on Mar 25, 2011 at 18:47 UTC
    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.

        Sorry. I posted the wrong version of the code. I have tried so many variations.


        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.