From: jik@athena.mit.edu (Jonathan I. Kamens)
Newsgroups: comp.lang.perl
Subject: 4.035 memory leak in very basic functionality
Date: 23 Nov 1992 04:33:29 GMT
Organization: Massachusetts Institute of Technology
Distribution: world
NNTP-Posting-Host: pit-manager.mit.edu

When I run this perl script:

#!/usr/local/bin/perl

open(TERMCAP, "/etc/termcap") || die;

foreach (1..100) {
    system("ps aux$$");
    if ($_ % 2 == 0) {
	while (<TERMCAP>) {
	}
	seek(TERMCAP, 0, 0);
    }
    else {
    }
}

I get this output:

USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  2.2  1.9  438  382 p0 S     0:00  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  0.4  1.6  438  320 p0 S     0:00  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  4.5  1.6  470  310 p0 S     0:01  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  2.4  1.6  470  300 p0 S     0:02  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  5.7  1.5  486  286 p0 S     0:04  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  3.4  1.5  486  276 p0 S     0:04  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  5.5  1.5  502  268 p0 S     0:06  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  3.7  1.5  502  266 p0 S     0:07  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  6.6  1.5  518  268 p0 S     0:07  (perl)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3108  4.2  1.7  518  328 p0 S     0:08  (perl)

I generally don't let it run for all 100 iterations, but as far as I've let
it, the trend you see continues -- the size of the process grows by 18k every
other time through the loop.  Note that I only do the reading every other
time through the loop in order to make sure that the system() isn't what's
causing the growth.

Here's a C program which does exactly the same thing as the perl script above:

#include <stdio.h>

main()
{
     int i;
     char cmd_buf[BUFSIZ];
     FILE *termcap;
     char read_buf[BUFSIZ];

     sprintf(cmd_buf, "ps aux%d", getpid());

     if (! (termcap = fopen("/etc/termcap", "r"))) {
	  perror("fopen");
	  exit(-1);
     }
     
     for (i = 0; i < 100; i++) {
	  system(cmd_buf);
	  if (i % 2 == 0) {
	       while (fgets(read_buf, sizeof(read_buf), termcap)) {
	       }
	       fseek(read_buf, 0L, 0);
	  }
	  else {
	  }
     }
}     

When I compile and run it, I get this output:

USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  0.7  0.3   36   32 p0 S     0:00  (a.out)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  1.7  0.4   46   40 p0 S     0:00  (a.out)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  0.7  0.4   46   40 p0 S     0:00  (a.out)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  0.3  0.4   46   40 p0 S     0:00  (a.out)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  0.1  0.4   46   40 p0 S     0:00  (a.out)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  0.1  0.4   46   40 p0 S     0:00  (a.out)
USER       PID %CPU %MEM   SZ  RSS TT STAT  TIME COMMAND
jik       3212  0.0  0.4   46   40 p0 S     0:00  (a.out)

As you can see, it does *not* grow after any initial growth.

Therefore, the growth in the perl process while the script is running can't be
due to stdio bugs on my platform, because a C program using the same stdio
routines that perl should be using does not grow.  It seems to me that it must
be a perl bug, but it is surprising to me that a memory leak should exist in
perl in something as simple as reading a file in a loop.

-- 
Jonathan Kamens                                         jik@MIT.Edu
MIT Information Systems/Athena              Moderator, news.answers