Hi,
I'm using the XS stack macros to call a method that returns a reference to
an array. The way I think I should do it performs correctly but emits
spurious warnings of "Attempt to free unreferenced scalar..." When I try to
eliminate that message by toying with reference counts and mortality I get
burned by either failed attempts and/or memory leaks.
Here's some test code showing my utter confusion:
use strict;
use warnings;
package Mod;
sub new {
return bless [ 'meh' ], shift;
}
sub foo {
return [ 0..$_[1]-1 ];
}
package main;
my $m = Mod->new;
for ( 1..10000 ) {
# my $v = foo($m,30);
test($m,30);
print "Iteration: $_\n" unless $_ % 10_000;
}
use Inline C => <<'EOC';
SV* foo(SV* mod,SV* upto) {
SV* values;
int count;
int i;
dSP;
PUSHMARK(SP);
XPUSHs(mod);
XPUSHs(sv_mortalcopy(upto));
PUTBACK;
count = call_method( "Mod::foo", G_SCALAR );
SPAGAIN;
if ( count != 1 )
croak("Mod::foo didn't return a sole value.");
values = POPs;
PUTBACK;
// Horrible, stops the warnings but causes leaks
// SvREFCNT_inc(values);
if ( SvTYPE(SvRV(values)) != SVt_PVAV )
croak("Mod::foo didn't return a reference to an array.");
// printf("Reference count of [ref,array]:
[%i,%i]\n",SvREFCNT(values),SvREFCNT((SV*)SvRV(values)));
// return values;
return sv_2mortal(values);
}
void test(SV* mod,SV* upto) {
int i;
SV* values;
// values = foo(mod,upto);
values = newSV(0);
for ( i = 0; i < 10; i++ ) {
sv_setsv(values,foo(mod,upto));
//Copying the array to a new reference ups its reference count to 2:
SvREFCNT_dec((SV*)SvRV(values)); // emits warnings
if ( SvIV(upto) != (int)(av_len( (AV*)SvRV(values) ))+1)
croak("Length of array != %i",SvIV(upto));
}
for ( i = 0; i < (int)(av_len( (AV*)SvRV(values) )) + 1; i++ ) {
if ( i != SvIV((SV*)*av_fetch( (AV*)SvRV(values), i, 0 )) )
croak("Bad value");
}
// printf("Ref count of [ref,array]:
[%i,%i]\n",SvREFCNT(values),SvREFCNT((SV*)SvRV(values)));
}
EOC
Thanks very much for any pointers,
Blake