Memory leaks are blocks of allocated memory that the program no longer references. Memory leaks are bugs and should always be fixed. Leaks waste space by filling up pages of memory with inaccessible data and waste time due to extra paging activity. Leaked memory eventually forces the system to allocate additional virtual memory pages for the application, the allocation of which could have been avoided by reclaiming the leaked memory.
The malloc library can only reclaim the memory you tell it to reclaim. If you call malloc
or any routine that allocates memory, you must balance that call with a corresponding free
. A typical memory leak occurs when a developer forgets to deallocate memory for a pointer embedded in a data structure. If you allocate memory for embedded pointers in your code, make sure you release the memory for that pointer prior to deallocating the data structure itself.
Another typical memory leak example occurs when a developer allocates memory, assigns it to a pointer, and then assigns a different value to the pointer without freeing the first block of memory. In this example, overwriting the address in the pointer erases the reference to the original block of memory, making it impossible to release.
Apple provides the MallocDebug application and leaks
command-line tool for automatically tracking down memory leaks. You can also track down leaks manually using other analysis tools, but that task falls under the category of finding memory problems in general and is covered in “Tracking Memory Usage.” The following sections describe the MallocDebug and leaks
tools and show you how to use them to track down memory leaks.
The Instruments application can be used to find leaks in both Mac OS X and iPhone applications. To find leaks, create a new document template in the application and add the Leaks instrument to it. The Leaks instrument provides leak-detection capabilities identical to those in the leaks
command-line tool. The Leaks instrument records all allocation events that occur in your application and then periodically searches the application’s writable memory, registers, and stack for references to any active memory blocks. If it does not find a reference to a block in one of these places, it deems the block a “leak” and displays the relevant information in the Detail pane.
In the Detail pane, you can view leaked memory blocks using Table and Outline modes. In Table mode, Instruments displays the complete list of leaked blocks, sorted by size. Selecting an entry in the table and clicking the arrow button next to the memory address shows the allocation history for the memory block at that address. Selecting an entry from this allocation history then shows the stack trace for that event in the Extended Detail pane of the document window. In Outline mode, the Leaks instrument displays leaks organized by call tree, which you can use to get information about the leaks in a particular branch of your code.
For more information about using the Instruments application, including more information about the information displayed by the Leaks instrument, see Instruments User Guide.
The MallocDebug application includes a memory-leak analysis tool that you can use to identify leaks in your Mac OS X applications. The interface for MallocDebug displays potential leaks using a call-graph structure so that you can easily locate the function that generated the leak.
MallocDebug uses a conservative garbage-collection algorithm for detecting leaks. This algorithm searches the program’s memory for pointers to each malloc-allocated block. Any block that is not referenced at all by the program is marked as a leak.
To initiate a leak search in MallocDebug, do the following:
Launch MallocDebug.
Open a new window and select the executable you want to examine.
Click the Launch button.
Exercise the application features to build its memory profile.
In MallocDebug, select “Leaks” from the analysis popup menu to display the memory leaks in your application.
Use the call-graph data in the browser to find where the memory was allocated.
Figure 1 shows the MallocDebug main window with the Leaks option selected for viewing. When you select any of the leak-related options from this popup menu, MallocDebug initiates its leak-detection analysis. It then displays the results of the analysis in the browser window. Each entry in the browser includes the amount of memory leaked from that function.
The leak analysis performed by MallocDebug identifies all memory that has been leaked since the application was launched. “Finding Leaks for Specific Features” describes a way you can use MallocDebug to isolate memory leaks in your application.
The leak analysis tools in MallocDebug perform a global search for leaks in your program. However, there are other types of leaks that MallocDebug cannot identify. These are leaks caused by your code allocating a block and then not freeing it. You must identify these leaks yourself using the MallocDebug sampling features. To find these leaks, do the following:
In the MallocDebug window, select "Allocations from mark" from the analysis popup button.
Click the Mark button.
Exercise the target feature of your application.
In MallocDebug, click the Update button to display the memory allocated since the Mark button was clicked.
Look for any newly-allocated buffers. These may be buffers your code forgot to free after it was done with them.
In Mac OS X, the leaks
command-line tool searches the virtual memory space of a process for buffers that were allocated by malloc
but are no longer referenced. For each leaked buffer it finds, leaks
displays the following information:
the address of the leaked memory
the size of the leak (in bytes)
the contents of the leaked buffer
If leaks
can determine that the object is an instance of an Objective-C or Core Foundation object, it also displays the name of the object. If you do not want to view the contents of each leaked buffer, you can specify the -nocontext
option when calling leaks
. If the MallocStackLogging
environment variable is set and you are running your application in gdb
, leaks
displays a stack trace describing where the buffer was allocated. For more information on malloc
debugging options, see “Enabling the Malloc Debugging Features.”
The leaks
tool has some advantages over MallocDebug when it comes to detecting leaks in complex data structures. For example, the leaks
tool correctly handles leaks in circularly linked structures. It can also identify leaks in groups of connected nodes. MallocDebug may not correctly identify leaks in these types of structures.
If a Cocoa object is autoreleased without an autorelease pool in place, Xcode sends an a message to the console warning you that the object is just leaking. Even if you are not writing a Cocoa application, it is possible to see this same type of console warning. The implementation of many Cocoa classes is based on Core Foundation types. If your application uses Core Foundation, it is possible that the leaks are occurring as a result of calls to that framework.
To find memory leaks of this type, use the debugger to put a breakpoint on the _NSAutoreleaseNoPool
function. This function is declared in NSDebug.h
in the Foundation framework. When the debugger reaches that function, you should be able to look at the stack crawl and see what piece of code caused the leak.
The following guidelines can help you find memory leaks quickly in your program. Most of these guidelines are intended to be used with the leaks
tool but some are also applicable for use with MallocDebug and general use.
Run leaks
during unit testing. Because unit testing exercises all code paths in a repeatable manner, you are more likely to find leaks than you would be if you were testing your code in a production environment.
Enable the MallocScribble
and MallocPreScribble
environment variables before running your leak tests. For more information, see “Enabling the Malloc Debugging Features.”
Use the -exclude
option of leaks
to filter out leaks in functions with known memory leaks. This option helps reduce the amount of extraneous information reported by leaks
.
If leaks
reports a leak intermittently, set up a loop around the target code path and run the code hundreds or thousands of times. This increases the likelihood of the leak reappearing more regularly.
Run your program against libgmalloc.dylib
in gdb
. This library is an aggressive debugging malloc library that can help track down insidious bugs in your code. For more information, see the libgmalloc
man page.
For Cocoa and iPhone applications, if you fix a leak and your program starts crashing, your code is probably trying to use an already-freed object or memory buffer. Set the NSZombieEnabled
environment variable to YES
to find messages to already freed objects.
Most unit testing code executes the desired code paths and exits. Although this is perfectly normal for unit testing, it creates a problem for the leaks
tool, which needs time to analyze the process memory space. To fix this problem, you should make sure your unit-testing code does not exit immediately upon completing its tests. You can do this by putting the process to sleep indefinitely instead of exiting normally.
Last updated: 2008-07-02