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);
> /* 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);
      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
-- 
$_=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