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

Reply via email to