On Thu, Feb 12, 2004 at 09:30:18AM +0000 Nick Ing-Simmons wrote: > 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.
You are right, a mortal isn't a terribly good idea here. But a non-mortal copy should do. Or simply incrementing s' refcount. Tassilo -- $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({ pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#; $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval