polettix has asked for the wisdom of the Perl Monks concerning the following question:
I always get stuck with memory leak problems when I try to use Perl from C (my very first post here was about this), but this time I can't believe that the problem is due to a bug in perl!
I'm using this with perl 5.8.8 in Linux. The main() function initialises the Perl stuff. The main objective is doing some cycles(), in which I repeatedly create an array and populate it (create_av()) and then dispose it. At some given intervals I print the memory status (print_memory()). Here's what I got (after filtering out most lines):/* Call this file arrays.c, and compile with: gcc -o arrays arrays.c `perl -MExtUtils::Embed -e ccopts -e ldopts` In my system: perl -MExtUtils::Embed -e ccopts -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOU +RCE -D_FILE_OFFSET_BITS=64 -I/opt/perl/lib/5.8.8/i686-linux/CORE perl -MExtUtils::Embed -e ldopts -Wl,-E -L/usr/local/lib /opt/perl/lib/5.8.8/i686-linux/auto/Dyn +aLoader/DynaLoader.a -L/opt/perl/lib/5.8.8/i686-linux/CORE -lperl -ln +sl -ldl -lm -lcrypt -lutil -lc */ #include <EXTERN.h> #include <perl.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> #define ELEMENTS 100000 #define ROUNDS 1000 #define MILESTONE 100 static PerlInterpreter *my_perl; AV* create_av () { AV *av = newAV(); int i; for (i = 0; i < ELEMENTS; ++i) { av_push(av, newSViv(i)); } return av; } void print_memory (int milestone) { FILE *fh; int nread; const int bufsize = 4096; char buffer[bufsize]; printf("\n\n**** %d ****\n", milestone); sprintf(buffer, "/proc/%d/status", getpid()); fh = fopen(buffer, "r"); while ((nread = fread(buffer, 1, bufsize, fh)) > 0) { fwrite(buffer, 1, nread, stdout); } } void cycles () { int i; for (i = 1; i <= ROUNDS; i++) { AV *av = create_av(); if (i % MILESTONE == 0) { print_memory(i); } av_undef(av); } } int main (int argc, char *argv[], char *env[]) { static char *dummy_argv[] = {"","-e","0"}; static int dummy_argc = 3; PERL_SYS_INIT3(&dummy_argc, &dummy_argv, &env); my_perl = perl_alloc(); perl_construct(my_perl); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_parse(my_perl, NULL, dummy_argc, dummy_argv, (char **) NULL); cycles(); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); return 0; }
I tried different values for the constants (ELEMENTS, ROUNDS and MILESTONE), but the trend remains: the more the cycles, the bigger the memory.**** 100 **** VmSize: 5528 kB **** 200 **** VmSize: 5536 kB **** 300 **** VmSize: 5544 kB **** 400 **** VmSize: 5816 kB **** 500 **** VmSize: 5824 kB **** 600 **** VmSize: 5832 kB **** 700 **** VmSize: 5840 kB **** 800 **** VmSize: 5848 kB **** 900 **** VmSize: 5860 kB **** 1000 **** VmSize: 5868 kB
Where am I leaking it?
Update: it turned out that I had two leaks: I had to use SvREFCNT_dec(av) instead of av_undef(av) and.. to close the filehandle I used to read the memory usage. Thanks to dave_the_m for spotting them both (what are you waiting? Go vote him!).
Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Memory leak dealing with AVs
by dave_the_m (Monsignor) on Sep 22, 2006 at 23:06 UTC | |
by polettix (Vicar) on Sep 23, 2006 at 09:18 UTC | |
by dave_the_m (Monsignor) on Sep 23, 2006 at 11:21 UTC | |
by polettix (Vicar) on Sep 23, 2006 at 15:16 UTC | |
|
Re: Memory leak dealing with AVs
by chromatic (Archbishop) on Sep 22, 2006 at 22:43 UTC |