in reply to XS/Inline::C concat *any* two SVs.

Why, given that SV *a is created in the Perl code and is not going out of scope, do I have to increment the ref count when I return it to Perl in order to avoid Attempt to free unreferenced scalar: SV 0x182445c, Perl interpreter: 0x2240d4.?

In your sub:
SV* test( SV *a, SV *b ) {
you get copy of scalars and not references to them. Not C but Perl will create a copy for you and pass to your subroutine. So you will see reference count in your sub equals to 1 even if you make some references to your scalar before calling your sub.
Insert couple of print statements to see your SVs parameters.

You make quite inconsistent thing in your C subroutine, at the very first step. You either replace SV *a with a new SV or do not, based on its constant-ness. Its a hole for scalar leaks. And may be your comment "// Why do I need to increment the ref count?" will go away. What will happen if you do not do "REFCNT_inc" exactly? Will the subroutine work for non-constant scalars?

Why not write following way:

SV* test( SV *a, SV *b ) { SV *c = newSVsv(a); sv_catsv(c,b); return c; }
As a side note, Inline::C is perfect for trivial cases, but when dealing with refernce counts and stuff you'll get another layer of hidden mechanics, so you'll have things under better control if you'll go to XS directly.
IOW Inline::C helps a great deal at the beginning, but it will add uncertainity after complexity grows a little.

Replies are listed 'Best First'.
Re^2: XS/Inline::C concat *any* two SVs.
by BrowserUk (Patriarch) on May 28, 2006 at 08:18 UTC
    You make quite inconsistent thing in your C subroutine, at the very first step. You either replace SV *a with a new SV or do not, based on its constant-ness. Its a hole for scalar leaks.

    I make a copy of the SV*a if it is readonly because otherwise I will get Modification of a read-only value attempted at c:\test\test.pl line 24. when I attempt to append to it. Otherwise, there is no need to copy rw scalars.

    What will happen if you do not do "REFCNT_inc" exactly? Will the subroutine work for non-constant scalars?

    If I do not increment the refcount, I get <c>

    c:\test>test billfred fred billfred Attempt to free unreferenced scalar: SV 0x182445c, Perl interpreter: 0 +x2240d4 at c:\test\test.pl line 32. 1fred Attempt to free unreferenced scalar: SV 0x182445c, Perl interpreter: 0 +x2240d4 at c:\test\test.pl line 35. 1 Attempt to free unreferenced scalar: SV 0x182445c, Perl interpreter: 0 +x2240d4. Attempt to free unreferenced scalar: SV 0x182445c, Perl interpreter: 0 +x2240d4.
    Why not write following way: ...

    Using your version, which is close to where I started, I get the following results:

    c:\test>test billfred Use of uninitialized value in subroutine entry at c:\test\test.pl line + 35. fred billfred 1fred 11

    Note:

    • The warning if SV*a was undefined.
    • How the modification does not change the source.

      Ie. With my version, '1' becomes '1fred' becomes '1fred1'.

      With yours, '1' becomes '1fred', then becomes '11'.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I tried and indeed got results you described.

      But given "my version" behaves as it should be. Please explain why it is not.

      You need concatenation SV subroutine - you get it. You receive 'undefined' warning when SV is indeed undefined, this warning could perfectly avoided, but chunk of code do what it is asked to.

      #! perl -slw use strict; use Inline C => << '__C__', NAME => 'test', CLEAN_AFTER_BUILD => 0; #include <stdio.h> SV* test( SV *a, SV *b ) { SV *c = newSVsv(a); sv_catsv(c,b); return c; } __C__ print test( 'bill', 'fred' ); my( $p, $q ) = ( 'fred' ); print test( $q, $p ); $q = 'bill'; print test( $q, $p ); $q = 1; print test( $q, $p ); $p = 1; print test( $q, $p );
      Right now, all is behaving, even w/o refcnt mess.
      Or do you want inplace editing of scalar? Then you need to pass a reference to SV and in the very beginning of subroutine dereference it once!

      BR,
      Vadim.

        Right now, all is behaving, even w/o refcnt mess

        The code in the OP does exactly what I need it to do. The equivalent of Perl's $scalar1 .= $scalar2;. Your version does not.

        I want, and need to accumulate the appended data in the original SV.

        The question is why do I need to increment the ref count, not how to avoid doing so. The problem with your approach is that you are completely discarding the benefits of Perl's dynamic string management.

        Your code is roughly equivalent to

        my $scalar3 = $scalar1; $scalar3 .= $scalar2;

        Which is not what I need. I would have to do

        my $scalar3 = $scalar1; $scalar3 .= $scalar2; $scalar1 = $scalar3;

        to get what I need and that is very wasteful as this will be called many (100s) of times to append 4 bytes each time.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      Drawing on the code that has so far been presented, it looks to me that you might want:
      SV* test( SV *a, SV *b ) { SV * c; if(SvREADONLY(a)) { c = newSVsv(a); sv_catsv(c, b); return c; } sv_catsv(a,b); c = newSVsv(a); return c; }
      I don't know how to avoid the "uninitialized value in subroutine entry" warning (apart from the obvious). Predicting whether you're going to get it or not is a little tricky. Of the 2 following subs, only test5() produces the warning for me:
      SV * test4(SV * a, SV * b){return newSVuv(42);} SV * test5(char * a, char * b){return newSVuv(42);}
      And if I comment out the sv_catsv() call in the code that vkon posted, then the warning disappears. Obviously the exact nature of what the xsub does has a bearing on whether we get that warning.

      Cheers,
      Rob

        The code I posted in the OP now does what I need it to do. Basically the XS equivalent of Perl's

        $scalar1 .= $scalar2;

        I don't want to create a new scalar, except in the specific instance of a readonly input. The routine will be called many times and I need to accumulate the results in the scalar.

        Duplicating the (already appended to), scalar in order to avoid using SvREFCOUNT_inc() is extremely wasteful and completely negates the benefits of perl's dynamically allocated string management. You have a scalar with n bytes, you call sv_catsv() to add m bytes to it. Having done that, you make a complete copy of m+n bytes in order to avoid the unreferenced scalar warning? This makes no sense to me, especially as the scalar of n bytes originates from Perl and has never gone out of scope.

        My question still remains, why am I getting that warning?

        The question is are there any other things that I need to test for and handle in order that I can handle any pair of SVs as input.

        And if I comment out the sv_catsv() call ...

        That is the (other) problem. If you call an SV that is undef as the first parameter to sv_catsv(), (which it usually will be on the first call for a particular SV), you get the warning. Hence the need for

        if( !SvPOK( a ) ) // Still nothing, must be undef? sv_setpv( a, "" ); // Make it the null string to stop (one pos +sible) // Use of uninitialized value in subroutine entry from sv_cats +v

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.