Locating Memory Leaks with MallocDebug

I am currently working on a interesting project written in C (more about the project in a few days or weeks) which requires a very clean memory management. I decided to write it in C because it does pretty long and complex calculations and I wanted to do it fast. But using C also means to do the whole memory management by myself. This can be a very hard job especially if a program is very memory-intensive.

Technorati Tags: ,

One of the biggest issue in memory management is to track down memory leaks.
“A memory leak is a particular kind of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed.” (Wikipedia).
If a computer program does not use a lot of memory a memory leak might not even be recognized by the programmer or the user. It looks differently if a program does a lot of malloc()’s and free()’s. Unreleased memory will be wasted and your program will get slower until your main memory is full.

Here is a typical example of how a memory leak is opened:

#include <stdio.h>
#include <stdlib.h>

void initA(int **aPtr) {
    *aPtr = (int*)malloc(sizeof(int));
}

void initB(int **bPtr) {
    *bPtr = (int*)malloc(sizeof(int));
}

int main(int argc, const char * argv[]) {
    int *aPtr;
    int *bPtr;

    initA(&aPtr);
    initB(&bPtr);

    aPtr = bPtr;

    // don't exit immediately
    getchar();

    return 0;
}

In this example we create two integer pointers (aPtr and bPtr) and two initialization functions (initA() and initB()) which will allocate memory for our two pointers.
After the initialization we assign bPtr to aPtr.
At this point we have a memory leak. Why? Because we deleted our only reference to the memory location stored in aPtr we can never reach that memory location again. It’s lost - forever (well, until our program exits).
In this example the memory leak is more or less obvious. But think of a multi hundred line C code program with structs and other funny C stuff. Locating memory leaks is nearly impossible - without any tools.

Fortunately, Apple ships a tool called MallocDebug with it’s Xcode IDE. With MallocDebug the developer get’s the chance to see where the unreachable memory (if any) was originally allocated. Following the corresponding pointer might lead to the location in the code where the leak occurs.

Let’s use the above example to take a look at MallocDebug.
Create a new Xcode project using the Standard Tool template. Paste the above code in your main.c file and try to compile and run it. You shouldn’t see any warnings or errors.
The getchar() call just prevents our little program from immediate termination because MallocDebug can only analyze the memory while the program is running.
To start MallocDebug, simply select Launch Using Performance Tool -> MallocDebug from Xcode’s Debug menu.

Start MallocDebug

MallocDebug will be started, but not our program. Select the MallocDebug window and click on the Launch button. Now our program will be started. In the current view you can see that our programm takes about 650K of memory. Feel free to browse through the tree to see where this memory is used.

All Allocations

To find leaks, select Leaks from the second drop-down menu.

Selecting Leaks

After a short time you can see, that 4 bytes originally allocated in initA() are lost.

Show Leaks

Add the following line before the line where we assign bPtr to aPtr:

free(aPtr);

Compile the program and run MallocDebug again. As expected we won’t have a leak anymore. The freed memory was returned to the operating system and can be assigned to the next process requesting memory. Great!

4 Responses to “Locating Memory Leaks with MallocDebug”


  1. 1 Simon

    Have you tried this in Leopard? I used your example but MallocDebug doesn’t see the leak. Strange…

  2. 2 Simon

    You’re right. The example isn’t working on Leopard anymore. I’ll update it as soon as I found the reason. Thanks!

  3. 3 Emanuele

    Yes, the leaks(1) utility is definitely no longer working properly on Leopard. I filed a bug with Apple but I haven’t heard anything back about it.

    This is another example:

    include

    include

    include

    static void foo(void) { malloc(256); }

    static void leaks(void) { char cmd[64]; sprintf(cmd, “/usr/bin/leaks %u”, getpid()); system(cmd); }

    int main(void) { atexit(leaks);

    foo(); foo(); foo();

    return 0; }

  4. 4 NinjaArmadillo

    I’m currently trying to use MallocDebug I run it (Debug>Launch using performance tool>MallocDebug), I make sure it’s pointing the the right file, Then I click launch.

    It hangs for about a minutes then says “Read Data, Unable to read malloc from …”

    I’m using OS X 10.4.11 (Tiger?) Xcode Ver 2.4.1 Component versions Xcode IDE: 762.0 Xcode Core: 762.0 ToolSupport: 764.0

    Am I doing something wrong ? Please Help!

Leave a Reply