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 -- $_=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