4.5. DetectingMemoryLeaks

TAU's memory leak detection feature can be initiated by giving tau_compiler.sh the option -optDetectMemoryLeaks. For a demonstration consider this C++ program:


#include <stdio.h>
#include <malloc.h>


/* there is a memory leak in bar when it is invoked with 5 < value <= 15 */
int bar(int value)
{
  printf("Inside bar: %d\n", value);
  int *x;

  if (value > 5)
  {
    printf("looks like it came here from g!\n");
    x = (int *) malloc(sizeof(int) * value);
    x[2]= 2;
    /* do not free it! create a memory leak, unless the value is > 15 */
    if (value > 15) free(x);
  }
  else
  { /* value  <=5 no leak */
    printf("looks like it came here from foo!\n");
    x = (int *) malloc(sizeof(int) * 45);
    x[23]= 2;
    free(x);
  }
  return 0;
}
    
int g(int value)
{
  printf("Inside g: %d\n", value);
  return bar(value);
}

int foo(int value)
{
  printf("Inside f: %d\n", value);
  
  if (value > 5) g(value);
  else bar(value);
	
  return 0;
}
int main(int argc, char **argv)
{
  int *x;
  int *y;
  printf ("Inside main\n");

  foo(12); /* leak */
  foo(20); /* no leak */
  foo(2);  /* no leak */
  foo(13); /* leak */
}

Notice that bar fails to free allocated memory on input between 5 and 15 and that foo will call g that calls bar when the input to foo is greater than 5.

Now configuring TAU with -PROFILECALLPATH run the file by:

%> cd examples/memoryleakdetect/
%> make
%> ./simple
...
USER EVENTS Profile :NODE 0, CONTEXT 0, THREAD 0
---------------------------------------------------------------------------------------
NumSamples   MaxValue   MinValue  MeanValue  Std. Dev.  Event Name
---------------------------------------------------------------------------------------
         2         52         48         50          2  MEMORY LEAK! malloc size <file=simple.inst.cpp, line=18> : int g(int)   => int bar(int)  
         1         80         80         80          0  free size <file=simple.inst.cpp, line=21>
         1         80         80         80          0  free size <file=simple.inst.cpp, line=21> : int g(int)   => int bar(int)  
         1        180        180        180          0  free size <file=simple.inst.cpp, line=28>
         1        180        180        180          0  free size <file=simple.inst.cpp, line=28> : int foo(int)   => int bar(int)  
         3         80         48         60      14.24  malloc size <file=simple.inst.cpp, line=18>
         3         80         48         60      14.24  malloc size <file=simple.inst.cpp, line=18> : int g(int)   => int bar(int)  
         1        180        180        180          0  malloc size <file=simple.inst.cpp, line=26>
         1        180        180        180          0  malloc size <file=simple.inst.cpp, line=26> : int foo(int)   => int bar(int)  
---------------------------------------------------------------------------------------

Notice that the first row show the two Memory leaks along with the callpath tracing where the unallocated memory was requested.