Will this be a potential memory leak?

C

cyl

XS(get_array_ref)
{
AV *av;
int i;
dXSARGS;

av = newAV();
i=10;
while(i--){
SV *sv = newSViv(i);
av_push(av,sv);
}
ST(0) = sv_2mortal(newRV((SV*)av));
XSRETURN(1);
}

If I run the code above for 100 times, for example

for (1..100){
my $ref = get_array_ref();
}

the memory size will increase about 20K. To reduce the memory usage I
add another code to free the list

for (1..100){
my $ref = get_array_ref();
@$ref = ();
}

this time the memory size increased about 8K. Using "undef $ref" did
not improve. Any suggestions for this? Thanks.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
cyl
XS(get_array_ref)
{
AV *av;
int i;
dXSARGS;

av = newAV();
i=10;
while(i--){
SV *sv = newSViv(i);
av_push(av,sv);
}
ST(0) = sv_2mortal(newRV((SV*)av)); ^^^^^
newRV_noref() (sp?)

XSRETURN(1);
}

If I run the code above for 100 times, for example

Hope this helps,
Ilya
 
C

cyl

[A complimentary Cc of this posting was sent to
cyl
{
AV *av;
int i;
dXSARGS;
av = newAV();
i=10;
while(i--){
SV *sv = newSViv(i);
av_push(av,sv);
}
ST(0) = sv_2mortal(newRV((SV*)av));

^^^^^
newRV_noref() (sp?)
XSRETURN(1);
}

I think you mean newRV_noinc(). With this change no memory increased.
But I am wondering what the lifetime of the array reference is. Will
there be any risk on data corruption when accessing the reference?
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
cyl
I think you mean newRV_noinc(). With this change no memory increased.
But I am wondering what the lifetime of the array reference is. Will
there be any risk on data corruption when accessing the reference?

There is no notion of "risk" in programming. There is correct code,
and incorrect code ;-). The code above has correct refcounts (here rv
is the return value of newRV_noinc() call):

av(short-time) av(long-time) rv(short-time) rv(long-time)
1 1 after newAV()
1 1 1 1 after newRV_noinc()
1 1 1 0 after sv_2mortal()

SVs returned from XSUBS should have long-time refcount 0 (unless
stored in long-time C pointers; then the refcount should be
incremented correspondingly). av is stored in rv only, so must
have long-time refcount 1. Thus your code is correct.

-------------------------------------------------------
If you had

static AV* stored_array;

....
stored_array = av;
ST(0) = sv_2mortal(newRV((SV*)av));

then the code would be also correct:

av(short-time) av(long-time) rv(short-time) rv(long-time)
1 1 after newAV()
2 2 1 1 after newRV()
2 2 1 0 after sv_2mortal()

now av is referenced from rv and stored_array, so must have long-time
refcount 2 (and you must change refcount manually when stored_array
value is changing).

-------------------------------------------------------
If you had

static SV* stored_ref;

....
SV *rv = newRV_noinc(av)
stored_ref = rv;
ST(0) = rv;

The refcounts would also be correct:

av(short-time) av(long-time) rv(short-time) rv(long-time)
1 1 after newAV()
1 1 1 1 after newRV_noinc()

Now av is stored only in rv, and rv is stored only in stored_ref. So
both long-time refcounts should be 1 on return from XSUB. And they are!

There is no need to sv_2mortal(), since its only purpose is that
short-time refcount of 0 is not possible. So if you need long-time
refcount of 0, you must arrange that REFCNT is decremented at some
later time.

Hope this helps,
Ilya

P.S. There are thousands of different ways to achieve the required
long-time refcounts, by doing arbitrary combinations of
SvREFCNT_inc/dec, different types of newRV, mortalization.

I did not try to achieve a combination which reflects best the
intenet of the programs. All I did was to use fewest number of
calls to reach this target. For example, in stored_array
example, it might be clearer to use newRV_noinc() followed by
SvREFCNT_inc().

P.P.S. Completely untested, and write-only. ;-)
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top