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