Finding Memory Leaks
Memory leaks are blocks of allocated memory that the program no longer references. 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.
For apps that use malloc, memory leaks are bugs and should always be fixed. For apps that use only Objective-C objects, the compiler’s ARC feature deallocates objects for you and generally avoids the problem of memory leaks. However, apps that mix the use of Objective-C objects and C-based structures must manage the ownership of objects more directly to ensure that the objects are not leaked.
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 you forget 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 you allocate memory, assign it to a pointer, and then assign 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.
Finding Leaks Using Instruments
The Instruments application can be used to find leaks in both OS X and iPhone applications. To find leaks, create a new document template in Instruments 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.
Using the leaks Tool
In 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
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
leaks displays a stack trace describing where the buffer was allocated. For more information on
malloc debugging options, see Enabling the Malloc Debugging Features.
Tips for Improving Leak Detection
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 general use.
leaksduring 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.
leaksto filter out leaks in functions with known memory leaks. This option helps reduce the amount of extraneous information reported by
leaksreports 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
gdb. This library is an aggressive debugging malloc library that can help track down insidious bugs in your code. For more information, see the
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
NSZombieEnabledenvironment variable to
YESto 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.