http://www.perlmonks.org?node_id=503113


in reply to Inline::C - object accessor failure

I haven't used Inline::C very much, so I'm not really familiar with its idiosyncracies. I would have expected this:

use Inline 'C' => <<CEND; SV* x (HV* self) { SV** x_ref = hv_fetch( self, "x", 1, 0 ); return (x_ref ? *x_ref : &PL_sv_undef); } CEND
to work, but in fact it causes some nasty internal warnings:
Attempt to free temp prematurely: SV 0x816f1c4. Attempt to free unreferenced scalar: SV 0x816f1c4.
You'll only get the warnings if you have a DEBUGGING compile of perl, but they indicate a real problem! I'm not certain, but I would guess this is actually a bug in Inline::C. Update: it's actually a feature of XS – see rest of thread. Thanks sfink!

It seems that the following works correctly:

use Inline 'C' => <<CEND; void x (HV* self) { SV** x_ref = hv_fetch( self, "x", 1, 0 ); Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push (x_ref ? *x_ref : &PL_sv_undef); Inline_Stack_Done; } CEND

Replies are listed 'Best First'.
Re^2: Inline::C - object accessor failure
by sfink (Deacon) on Oct 26, 2005 at 17:57 UTC
    Actually, that's XS.

    In your first example, you're returning an SV* you looked up in the hash, so you don't own it. Inline::C works by generating an XS file and running xsubpp, and XS mortalizes any SV* that you return via its RETVAL mechanism. Thus, you've mortalized an SV* owned by the hash. Which is not at all pointed out by the Inline documentation (it should be in Inline::C-Cookbook), and the description in perlxs seems suspicious to me to (it claims that RETVAL is mortalized via the typemap file, but I'm looking at the typemap and I see no relevant mention of 'mortal' anywhere -- nor any mention of RETVAL.)

    So I think this should work:

    And it doesn't seem to leak, either: replace the last two lines with
    sub Whiner::DESTROY { print "Dying!\n" } my $t = InlineTest->new( x => bless [], 'Whiner' ); print $t->x, "\n"; undef $t; print "Done.\n";
    and it prints "Dying!" before "Done."

    In general, I would also recommend using <<'CEND' rather than <<CEND for blocks of Inline code, because if you want to insert a debugging printf("Got here!\n"), then you don't really want that \n to be translated to a newline.


    I work for Reactrix Systems, and am willing to admit it.
      ...XS mortalizes any SV* that you return via its RETVAL mechanism ... and the description in perlxs seems suspicious to me to (it claims that RETVAL is mortalized via the typemap file, but I'm looking at the typemap and I see no relevant mention of 'mortal' anywhere -- nor any mention of RETVAL.)
      Interestingly, RETVAL is mortalized by xsubpp itself (see the generate_output cruft in the xsubpp source) - so it is hardwired into XS... But it usually turns out to do what you want, except for the cases, when it does not.

      Wow, thanks! I've been looking at the 5.8.1 version of perlxs, which doesn't mention the automatic mortalization of RETVAL at all. It looks like that section was added in 5.8.4.

      (Inline was written quite a while before this feature was documented, so maybe ingy didn't know about it and that's why the Inline::C documentation doesn't mention it?)

      You'd think that not knowing about this would have caused me problems by now. The odd thing is, I've just looked over all my XS code and I don't seem to have run afoul of it anywhere. I suppose it helps that I usually use PPCODE instead of CODE.