Previous: Library functions, Up: Using mpatrol

7.8 Leak table

The mpatrol library provides a hash table called a leak table that can be used to record memory allocations and deallocations for the purpose of detecting memory leaks. It can be fully controlled from the source code of a program by calling the appropriate mpatrol library functions, but the mpatrol library can also be instructed to automatically enter the details of each memory event into the leak table by using the LEAKTABLE option.

The leak table records a flat profile of memory allocation behaviour between two points in a program and is keyed by source file location. What that means is, it contains an entry for each source file and line number that allocated memory, and if more than one memory allocation event occurred at that point then the entry will summarise the total events that occurred at that point. In many cases, the source file and line number is not available for a memory allocation event, in which case either the function name or the return address can be used instead.

The following example shows the use of the leak table manipulation functions.

      1  /*
      2   * Illustrates the explicit and implicit manipulation of the
      3   * leak table.
      4   */
      7  #include "mpatrol.h"
     10  int main(void)
     11  {
     12      void *p, *q;
     13      int r;
     15      __mp_clearleaktable();
     16      __mp_addallocentry("file.c", 1, 1);
     17      __mp_addfreeentry("file.c", 1, 1);
     18      __mp_addallocentry("file.c", 1, 2);
     19      __mp_addfreeentry("file.c", 1, 2);
     20      __mp_addallocentry("file.c", 1, 3);
     21      __mp_addfreeentry("file.c", 1, 3);
     22      __mp_addallocentry("function", 0, 8);
     23      __mp_addfreeentry("function", 0, 4);
     24      __mp_addallocentry("function", 0, 16);
     25      __mp_addfreeentry("function", 0, 12);
     26      __mp_addallocentry(NULL, 0x40000000, 8);
     27      r = __mp_startleaktable();
     28      if (p = malloc(16))
     29          if (q = realloc(p, 32))
     30              free(q);
     31          else
     32              free(p);
     33      if (r == 0)
     34          __mp_stopleaktable();
     35      __mp_leaktable(0, MP_LT_ALLOCATED, MP_LT_BOTTOM);
     36      __mp_printf("\n");
     37      __mp_leaktable(0, MP_LT_FREED, MP_LT_COUNTS);
     38      __mp_printf("\n");
     39      __mp_leaktable(0, MP_LT_UNFREED, 0);
     40      __mp_printf("\n");
     41      return EXIT_SUCCESS;
     42  }

The output that appears in mpatrol.log should look similar to this.

     bottom 5 allocated memory entries in leak table:
            bytes   count  location
         --------  ------  --------
                6       3  file.c line 1
                8       1  0x40000000
               16       1  test.c line 28
               24       2  function
               32       1  test.c line 29
               86       8  total
     top 4 freed memory entries in leak table:
          count     bytes  location
         ------  --------  --------
              3         6  file.c line 1
              2        16  function
              1        32  test.c line 29
              1        16  test.c line 28
              7        70  total
     top 2 unfreed memory entries in leak table:
            bytes   count  location
         --------  ------  --------
                8       1  0x40000000
                8       0  function
               16       1  total

Line 15 of the above program clears the leak table. This can be done as many times as necessary during the execution of the program, but note that there is only one leak table so this will affect the LEAKTABLE option. The following 6 lines then add matching allocation and deallocation entries to the leak table corresponding to a source location of line 1 in a file called file.c. Any deallocation entries must match the source position of the original allocation due to the nature of the leak table. Note that these 6 lines correspond to an allocation of 1 byte, followed by two reallocations of 2 and 3 bytes respectively, followed by a final deallocation.

Lines 22-23 allocate 8 bytes from a function called function() but only free 4 bytes, resulting in a memory leak of 4 bytes. Lines 24-25 do the same but allocate 16 bytes and free 12. The next line allocates 8 bytes from a code address of `0x40000000' but does not free it, resulting in a memory leak of 8 bytes. Note that if the line number is specified as `0' then the filename will be taken as a function name, and if the filename is specified as `NULL' then the line number will be taken as a return address. If neither are specified then the number of bytes will be added or subtracted from the `unknown' location.

Line 27 instructs mpatrol to automatically record any subsequent memory allocation events in the leak table, while line 34 does the opposite. The __mp_startleaktable() function returns `1' if automatic leak table recording was turned on and `0' otherwise, so we check in line 33 to see if we should turn off automatic recording by examining the previous state. Lines 28-32 allocate, reallocate and free some memory just to demonstrate this.

Finally, lines 35-40 display the contents of the memory leak table that have been recorded since the call to __mp_clearleaktable(). Three different types of display can be generated: allocated memory allocations, freed memory allocations and unfreed memory allocations. They can also be sorted by the total number of calls instead of the total number of bytes (MP_LT_COUNTS) or in reverse order with the smallest first (MP_LT_BOTTOM). The count of `0' in the last table indicates that there were a matching number of calls to allocate and free memory within function() but the number of bytes freed was less than the number of bytes allocated. This can only happen if the entries were added by __mp_addallocentry() and __mp_addfreeentry() and is usually an indication that something is wrong when making these calls.

The leak table is a useful tool to manipulate when debugging your application to check for memory leaks, but it is not as detailed as full memory allocation profiling which is controlled by the PROF option. It is probably better at summarising unfreed allocations than the SHOWUNFREED option but does not show the call stack for each allocation.

In addition, the __mp_iterate() function can be used within user code to obtain details about changes in the heap since a certain point in a program's execution. However, it can only provide details about freed memory allocations if the NOFREE option is used. The leak table will provide less details on freed memory allocations but its advantage is that it does not require the use of the NOFREE option.