Go to main content
Oracle® Developer Studio 12.6: Debugging a Program with dbx

Exit Print View

Updated: June 2017
 
 

Using Memory Leak Checking

A memory leak is a dynamically allocated block of memory that has no pointers pointing to it anywhere in the data space of the program. Such blocks are orphaned memory. Because no pointers are pointing to the blocks, programs cannot reference them, much less free them. Runtime checking finds and reports such blocks.

Memory leaks result in increased virtual memory consumption and generally result in memory fragmentation. This might slow down the performance of your program and the whole system.

Typically, memory leaks occur because allocated memory is not freed and you lose a pointer to the allocated block. Here are some examples of memory leaks:

void
foo()
{
    char *s;
    s = (char *) malloc(32);

    strcpy(s, "hello world");

    return; /* no free of s. Once foo returns, there is no     */
            /* pointer pointing to the malloc’ed block,         */
            /* so that block is leaked.                         */
}

A leak can result from incorrect use of an API.

void
printcwd()
{

    printf("cwd = %s\n", getcwd(NULL, MAXPATHLEN));

    return; /* libc function getcwd() returns a pointer to     */
            /* malloc’ed area when the first argument is NULL, */
            /* program should remember to free this. In this   */
            /* case the block is not freed and results in leak.*/
}

You can avoid memory leaks by always freeing memory when it is no longer needed and paying close attention to library functions that return allocated memory. If you use such functions, remember to free up the memory appropriately.

Sometimes the term memory leak is used to refer to any block that has not been freed. This definition is much less useful, because it is a common programming practice not to free memory if the program will terminate shortly. Runtime checking does not report a block as a leak if the program still retains one or more pointers to it.

Detecting Memory Leak Errors

Possible Leaks

Runtime checking can report a “possible” leak in two cases. The first case is when no pointers are found pointing to the beginning of the block but a pointer is found pointing to the interior of the block. This case is reported as an Address in block (aib) error. A stray pointer pointing into the block would be a real memory leak. However, some programs deliberately move the only pointer to an array back and forth as needed to access its entries. This case would not be a memory leak. Because runtime checking cannot distinguish between these two cases, it reports both of them as possible leaks, letting you determine which are real memory leaks.

The second type of possible leak occurs when no pointers to a block are found in the data space but a pointer is found in a register. This case is reported as an Address in register (air) error. If the register points to the block accidentally or if it is an old copy of a memory pointer that has since been lost, then this is a real leak. However, the compiler can optimize references and place the only pointer to a block in a register without ever writing the pointer to memory. Such a case would not be a real leak. Hence, if the program has been optimized and the report was the result of the showleaks command, it is likely not to be a real leak. In all other cases, it is likely to be a real leak. For more information, see showleaks Command.


Note -  Runtime leak checking requires the use of the standard libc malloc/free/realloc functions or allocators based on those functions. For other allocators, see Runtime Checking Application Programming Interface.

Checking for Leaks

If memory leak checking is enabled, a scan for memory leaks is automatically performed just before the program being tested exits. Any detected leaks are reported. The program should not be killed with the kill command. The following example is a typical memory leak error message:

Memory leak (mel):
Found leaked block of size 6 at address 0x21718
At time of allocation, the call stack was:
    [1] foo() at line 63 in test.c
    [2] main() at line 47 in test.c

A UNIX program has a main procedure (called MAIN in f77) that is the top-level user function for the program. Normally, a program terminates either by calling exit(3) or by returning from main. In the latter case, all variables local to main go out of scope after the return, and any heap blocks they pointed to are reported as leaks unless global variables point to those same blocks.

A common programming practice is not to free heap blocks allocated to local variables in main, because the program is about to terminate and return from main without calling exit(). To prevent runtime checking from reporting such blocks as memory leaks, stop the program just before main returns by setting a breakpoint on the last executable source line in main. When the program halts there, use the showleaks command to report all the true leaks, omitting the leaks that would result merely from variables in main going out of scope.

For more information, see showleaks Command.

Understanding the Memory Leak Report

With leak checking enabled, you receive an automatic leak report when the program exits. All possible leaks are reported, provided the program has not been killed using the kill command. The level of detail in the report is controlled by the dbxenv variable rtc_mel_at_exit. By default, a non-verbose leak report is generated.

Reports are sorted according to the combined size of the leaks. Actual memory leaks are reported first, followed by possible leaks. The verbose report contains detailed stack trace information, including line numbers and source files whenever they are available.

Both reports include the following information for memory leak errors:

Size

Size of leaked block

Location

Location where leaked block was allocated

Address

Address of leaked block

Stack

Call stack at time of allocation, as constrained by check -frames

The following is the corresponding non-verbose memory leak report.

Actual leaks report    (actual leaks:    3 total size:    2427 bytes)

 Total      Num of  Leaked      Allocation call stack
 Size       Blocks  Block
                    Address
==========  ====== ==========  =======================================
      1852       2      -      true_leak < true_leak
       575       1    0x22150  true_leak < main

Possible leaks report  (possible leaks:  1  total size:       8 bytes)

 Total      Num of  Leaked      Allocation call stack
 Size       Blocks  Block
                    Address
==========  ====== ==========  =======================================
         8       1    0x219b0  in_block < main

The following example shows a typical verbose leak report.

Actual leaks report    (actual leaks:         3  total size:    2427 bytes)

Memory Leak (mel):
Found 2 leaked blocks with total size 1852 bytes
At time of each allocation, the call stack was:
    [1] true_leak() at line 220 in "leaks.c"
    [2] true_leak() at line 224 in "leaks.c"

Memory Leak (mel):
Found leaked block of size 575 bytes at address 0x22150
At time of allocation, the call stack was:
    [1] true_leak() at line 220 in "leaks.c"
    [2] main() at line 87 in "leaks.c"

Possible leaks report  (possible leaks:       1  total size:       8 bytes)

Possible memory leak -- address in block (aib):
Found leaked block of size 8 bytes at address 0x219b0
At time of allocation, the call stack was:
    [1] in_block() at line 177 in "leaks.c"
    [2] main() at line 100 in "leaks.c"

Generating a Leak Report

You can ask for a leak report at any time using the showleaks command, which reports new memory leaks since the last showleaks command. For more information, see showleaks Command.

Combining Leaks

Because the number of individual leaks can be very large, runtime checking automatically combines leaks allocated at the same place into a single combined leak report. The decision to combine leaks, or report them individually, is controlled by the number-of-frames-to-match parameter specified by the -match m option on a check –leaks or the -m option of the showleaks command. If the call stack at the time of allocation for two or more leaks matches to m frames to the exact program counter level, these leaks are reported in a single combined leak report.

Consider the following three call sequences:

Block 1
Block 2
Block 3
[1] malloc
[1] malloc
[1] malloc
[2] d() at 0x20000
[2] d() at 0x20000
[2] d() at 0x20000
[3] c() at 0x30000
[3] c() at 0x30000
[3] c() at 0x31000
[4] b() at 0x40000
[4] b() at 0x41000
[4] b() at 0x40000
[5] a() at 0x50000
[5] a() at 0x50000
[5] a() at 0x50000

If all of these blocks lead to memory leaks, the value of m determines whether the leaks are reported as separate leaks or as one repeated leak. If m is 2, Blocks 1 and 2 are reported as one repeated leak because the 2 stack frames above malloc() are common to both call sequences. Block 3 will be reported as a separate leak because the trace for c() does not match the other blocks. For m greater than 2, runtime checking reports all leaks as separate leaks. The malloc is not shown on the leak report.

In general, the smaller the value of m, the fewer individual leak reports and the more combined leak reports are generated. The greater the value of m, the fewer combined leak reports and the more individual leak reports are generated.

Fixing Memory Leaks

Once you have obtained a memory leak report, follow these guidelines for fixing the memory leaks:

  • Most importantly, determine where the leak is. The leak report tells you the allocation trace of the leaked block, the place where the leaked block was allocated.

  • You can then look at the execution flow of your program and see how the block was used. If it is obvious where the pointer was lost, the job is easy; otherwise you can use showleaks to narrow your leak window. By default, the showleaks command lists the new leaks created only since the last showleaks command. You can run showleaks repeatedly while stepping through your program to narrow the window where the block was leaked.

For more information, see showleaks Command.