Tassilo Parseval <[EMAIL PROTECTED]> writes:
>On Thu, Feb 12, 2004 at 12:45:29PM +1100 Sisyphus wrote:
>
>> Below is a very simple Inline::C script - and, in case it's useful, 
>> below my sig is the XS file that Inline autogenerates from that script.
>> 
>> ----- start card.pl -----
>> use Inline C => <<'EOC';
>> 
>>      typedef struct {
>>        SV * suit;
>>        int value;
>>        } Card;
>> 
>> 
>> SV * create_structref(SV * s, int v) {
>>  Card * cptr;
>>  New(123, cptr, sizeof(Card), Card);
>>  if(cptr == NULL) croak("Failed to allocate memory");
>>  cptr->suit = s;
>>  cptr->value = v;
>>  return sv_setref_pv(newSViv(0), Nullch, cptr);
>> }
>> 
>> void clear_mem(SV * p) {
>>  Card* c = (Card *)SvIV(SvRV(p));
>>  printf("Clear_mem called\n");
>>  Safefree(c->suit);

You don't Savefree() SVs - you do SvREFCNT_dec() on them
and the memory gets linked to a pool for reuse.
You should normally SvRECNT_inc an SV that you are going to save
in a C struct so perl knows you are using it.


>> /* c->value is an int, and not to be Safefreed */
>>  Safefree(c);
>> }
>> 
>> EOC
>> 
>> $s_index = int(rand(4));
>> $s = ('Hearts', 'Clubs', 'Diamonds', 'Spades')[$s_index];
>> $v = int(rand(13)) + 1;
>> 
>> $c = create_structref($s, $v);
>> 
>> clear_mem($c);
>> 
>> __END__
>> ----- end card.pl ------
>> 
>> On win32, there's no problem with that (perl 5.6.1, 5.8.0, and 5.8.2).
>> 
>> On linux, where I have only perl 5.8.0, it prints:
>> 
>> Clear_mem called
>> Segmentation fault
>> 
>> I can get rid of the Segmentation fault by commenting out 
>> 'Safefree(c->suit);' in the 'clear_mem()' function.
>
>That is what I would expect. You pass $v to create_structref and store a
>pointer to it in c->suit. You should only manually free it when you
>copied the SV. Something like that:
>
>    SV * create_structref(SV * s, int v) {
>      Card * cptr;
>      New(123, cptr, sizeof(Card), Card);
>      cptr->suite = sv_mortalcopy(s);

A 'mortal' will be freed by perl on scope (statement) exit.



>      cptr->value = v;
>      ...
>    }
>
>    void clear_mem(SV *p) {
>      Card *c = (Card*)SvIV(SvRV(p));
>      sv_free(c->suit);
>      Safefree(c);
>    }
>
>Copying the SV is a good idea anyways because otherwise c->suit is
>destroyed when perl garbage-collects $v. If you don't want to create a
>copy, you should increment the refcount of 's' in create_structref. In
>this case you should also be able to store a pointer to s in your
>structure.
>
>Tassilo

Reply via email to