in reply to Perl XS: garbage-collecting my malloc'd buffer

Your original code didn't have a memory leak. [ Update: Rather, it needn't have a memory leak. Just remove the "buffer = (char *)malloc(len);" which I skipped over when I read it. (: ]

When you tell XS that you have a "char *" input buffer, it pulls out a pointer to the string value (if any) stored in the scalar you pass in. So that buffer is allocated just like any other scalar string value buffer in Perl and is free()d in the same situations. So you don't need to worry about a memory leak.

You could think of your original code as "inconvenient" or even "dangerous" because it requires the caller to pass in length($buffer) or at least a value that is smaller than the size of the buffer allocated to the "buffer" scalar that is passed in.

But I'd probably fix that by forcing the scalar to contain a buffer of the specified size before calling the C function:

int my_xs_func(p_struct, OUTLIST buffer, len) void *p_struct; SV *buffer; int len; CODE: { char *buf = sv_grow( buffer, len ); /* was: char *buf = SvGROW( buffer, len ); */ RETVAL = my_func( p_struct, buf, len ); } OUTPUT: RETVAL
see perlguts for more on SvGROW() (see also perlxstut, perlxs, etc.) (:

Updated to match what I'd use based on the feedback below.

                - tye

Replies are listed 'Best First'.
Re: Re: Perl XS: garbage-collecting my malloc'd buffer
by Thelonius (Priest) on Mar 03, 2003 at 18:01 UTC
    I think that before you SvGROW you should call SvPV_force. Otherwise (at least this was once true) SvGrow will choke if there is not already a buffer. So, the code would be:
    CODE: { int dummylen; SvPV_force(buffer, dummylen); char *buf = SvGROW( buffer, len ); RETVAL = my_func( p_struct, buf, len ); }
      Yep, that's still the case. SvGROW checks xpv_len, which'll be some bizarre value if the SV's just an IV or NV. Undef might well give it fits too, at least so reads the 5.8.0 sources.

        Wouldn't calling sv_grow() directly fix that?

                        - tye

      That was how I had originally written the code in my head then I checked the Perl v5.6.0 source code for SvGROW() and saw that such wasn't needed. It might be a problem for Perl versions prior to that, however. I know I jumped through more hoops when I wrote similar XS code ages ago -- I was hoping it had just been my lack of understanding. (:

      Update: I was mostly checking sv_grow() which is what the SvGROW() macro calls. See elsewhere in this thread for why I'm wrong above.

                      - tye