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: MallocDebug, memory leaks
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.

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.

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

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

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!

Have you tried this in Leopard? I used your example but MallocDebug doesn’t see the leak. Strange…
You’re right. The example isn’t working on Leopard anymore. I’ll update it as soon as I found the reason. Thanks!
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; }
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!