Thanks Tassilo!  I did not know about savepv, very convenient, like
strdup.  Just curious, is the the SV memory being re-used, or is it 
not going out of scope?  I didn't think it would be static.  


On Mon, 2004-04-19 at 12:54, Tassilo von Parseval wrote:
> On Mon, Apr 19, 2004 at 12:08:03PM -0500 Scott T. Hildreth wrote:
> 
> > I have a xsub that has a pointer to a c-structure, and a sv as the
> > parameters, 
> > 
> > IV
> > set_fld_name(fld, name)
> >     
> >     FLD * fld
> >     SV  * name
> >     PREINIT:
> >         STRLEN len;
> >     CODE:
> >         if (name == (SV *)NULL)
> >             RETVAL = 0;
> >         else {
> >             fld->name = SvPV(name, len);
> >             RETVAL = 1;
> >         }
> >     OUTPUT:
> >         RETVAL
> > 
> > 
> > ..which changes the name of a 'fld->name'. Which works fine if I only
> > change one name.  If the sub is called more than once the 'fld->name'
> > pointers all point to the same string.  The name is a my variable passed
> > in via a method, so I thought there would be an SV created, but the fld
> > names changed all point to the same memory, and have the same string.  I
> > used Devel::Peek to confirm that the address is same.  Here is the
> > method, 
> > 
> > sub set_name {
> >     my ($self, $fldnm) = @_;
> >     my $rc;                 
> >     my $newself = {};
> >                      
> >     $fldnm = lc $fldnm; #== Fmt is case insensitive.
> >     $rc = fmt_set_fld_name($self->{_ptr}, $fldnm);
> > 
> > .
> > .
> > .
> >      return $newself
> >  }
> > 
> >  .. so the address of $fldnm is always the same (static).  Therefore the
> > fld->names that are sent in all point to the same address.  How do I get
> > a new SV so that the memory area is different. 
> 
> By making a copy:
> 
>     fld->name = savepv( SvPV(name, len) );
> 
> If you don't do that, you'll sooner or later get corrupted memory. You
> pass a mortal scalar to the XSUB and use the pointer to its PV slot
> elsewhere. Perl doesn't know that and once it frees this scalar, the
> pointer is garbage as well.
> 
> Another thing you could probably do is not making a copy but
> incrementing the scalar's refcount:
> 
>     fld->name = SvPV(name, len);
>     SvREFCNT_inc(name);
> 
> and decrementing it accordingly once you no longer need to the pointer.
> 
> Tassilo

Reply via email to