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. :-(
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.