perl C extension

G

gmlvsk2

Simple code that creates new hash and put {'foo'=>5} to it
This works and prints 5, but does not release variable sv, so there is
memory leak
some function
HV *hv;
SV *sv = newSViv(5);
hv = newHV();
hv_store( hv, "foo", 3, sv, 0 );
return sv_2mortal( newRV((SV*)hv) );

If I change line 2 to
SV *sv = sv_2mortal( newSViv(5) );
I get undef instead of 5 during print, but the variable is released.

What do I do wrong here, how can mark variable for relese but still be
able to use it from hash

__________________________________________________
Perl to test
use Try;
use Data::Dumper;

$a = Try::foo();
#print $a->{'foo'}, "\n";
print Dumper( $a );
 
A

anno4000

Simple code that creates new hash and put {'foo'=>5} to it
This works and prints 5, but does not release variable sv, so there is
memory leak
some function
HV *hv;
SV *sv = newSViv(5);
hv = newHV();
hv_store( hv, "foo", 3, sv, 0 );
return sv_2mortal( newRV((SV*)hv) );

If I change line 2 to
SV *sv = sv_2mortal( newSViv(5) );
I get undef instead of 5 during print, but the variable is released.

What do I do wrong here, how can mark variable for relese but still be
able to use it from hash

__________________________________________________
Perl to test
use Try;
use Data::Dumper;

$a = Try::foo();
#print $a->{'foo'}, "\n";
print Dumper( $a );

Since your code isn't XS code, I suppose you were using Inline to
compile it.

As far as I can see you don't need sv_2mortal() at all in this example.
It is certainly wrong for the scalar you store in the hash. Since you
are not returning the value on the stack (only a hash that contains it)
the default refcounts are fine.

As for the return value, either Inline or XS auto-mortalizes it, I
believe. If you do it yourself that amounts to one too many.

The one thing that might want an sv_2mortal() is the hash itself.
It comes with a refcount of 1 which is increased to 2 by taking
the reference later. After the function returns, the return value
is the only reference to the hash, so the count is one high. You
can also compensate by using newRV_noinc() to take the ref.

The following snippet shows the three refcounts involved, that of the
hashref, that of the hash, and that of the scalar 5 the hash contains.
They are all 1 as they should be.

use Devel::peek;
Dump mk_hash();
exit;

use Inline C => <<'EOC';

SV* mk_hash() {
HV *hv;
SV *sv = newSViv(5);
hv = newHV();
hv_store( hv, "foo", 3, sv, 0 );
return newRV_noinc((SV*)hv);
}
EOC

Anno
 
G

gmlvsk2

Thanks,
If this helps I use SWIG and use this typemap to return result from
function
Does it make any difference?

%module Try
%include "typemaps.i"
%{
%}

%typemap(out) char* {
HV *hv;
SV *sv = sv_2mortal(newSViv(5));
hv = newHV();
hv_store( hv, "foo", 3, sv, 0 );
$result = sv_2mortal( newRV((SV*)hv) );
printf( "%d\n", SvREFCNT(sv) );
argvi++;
}

char* foo();
 
X

xhoster

Simple code that creates new hash and put {'foo'=>5} to it
This works and prints 5, but does not release variable sv, so there is
memory leak

I think the actual problem is that it does not release the hv. You need
to mortalize hv rather than (or maybe in addition to) mortalizing newRV(hv)
some function
HV *hv;
SV *sv = newSViv(5);
hv = newHV();
hv_store( hv, "foo", 3, sv, 0 );
return sv_2mortal( newRV((SV*)hv) );

If I change line 2 to
SV *sv = sv_2mortal( newSViv(5) );
I get undef instead of 5 during print, but the variable is released.

Sometimes freeing the wrong thing can eliminate a memory leak in a
different variable, for reasons I don't understand.

Xho
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top