to memleak or not to memleak

ethan on 2003-08-16T09:42:33

The following code should actually need more or less constant memory, right?

my $str = "a"; for (0 .. $i) { $str->nextI; # string autoincrement: "z" becomes "aa" print $str; }

But no, it doesn't. Depending on $i, it may eat well over 30meg. So naturally I suspected a memore-leak in my code and asked valgrind about it.

valgrind only finds 128 non-freed bytes, but those aren't by me but are allocated somewhere in the perl-interpreter. In my code, I naturally return a mortal SV and deallocate all my memory tidily. Very strange really.

Another thing I became aware of might be a problem with Perl's default typemaps.



char * func () PREINIT: char *string; CODE: string = func_that_returns_allocated_string(); RETVAL = string; OUTPUT: RETVAL



The 'char*' typemap copies the string pointed to by RETVAL into an SV and returns it. The thing is the copying. Since it is copied, I need to free the original string somehow, but I don't see how this is possible. Initially I used a lot of these default typemaps to return values and in fact valgrind reported small leaks for each of them. Perhaps I have to use the 'CLEANUP' directive for that.

Now I changed it to:

void func () PREINIT: char *string; PPCODE: string = func_that_returns_allocated_string(); XPUSHs(sv_2mortal(newSVpvn(string, strlen(string)))); Safefree(string); XSRETURN(1);

Anyway, this made the leaks go away (according to valgrind), so I guess I am on the right track here.

This didn't fix my problem with next and nextI though. :-(


reduce, reuse, recycle

nicholas on 2003-08-16T11:32:55

Rather than copying the malloc()ed string into an SV and then free()ing it, check out sv_usepvn which can directly take over the buffer. Sorry, I don't know the XS-fu to create a typemap to make your wrapper use this automatically.

Maybe that useful function should be re-named sv_borg to make it stand out more.

Re:reduce, reuse, recycle

ethan on 2003-08-16T14:18:01

[sv_usepvn]

Nice! I was looking for something like that. In fact, I always blindly assumed that the 'char *' typemap would only copy the pointer and not the whole vector (till I realized that it does exactly that yesterday).

I think this can be turned into a typemap easily. AFAIK, there is no default typemap for 'const char*' so I can use that.

Maybe that useful function should be re-named sv_borg to make it stand out more.
 
:-) Guess what: the curious Poison() macro did immediately spring into my eyes even though I don't see what I could ever use it for.