Tuesday, February 06, 2007

Quick and Easy Leaks Detection on Mac OS X

If you are using a Mac OS X machine and have Apple's Developer Tools, such as Xcode, on it, you have access to a very quick and easy way to check for memory leaks. Not everyone knows about this, though it has been available for at least a few versions of the Dev Tools, so I thought I would put this out.

If an application is running and you want to see if it is leaking memory, you can do run leaks and give it either a pid as a parameter, or a string matchable to the running process, such as "firefox-bin" or "thunderbird-bin". The string matching only works if only one such process is running. Here is an example:

$ leaks firefox
Found process 260 (firefox-bin) from partial name firefox
Process 260: 1263939 nodes malloced for 147066 KB
Process 260: 76194 leaks for 7262704 total leaked bytes.
Leak: 0x19aeea00 size=4096
0x0d0a0d30 0x6320740a 0x7373616c 0x7462223d
0x7420226e 0x3d657079 0x62757322 0x2274696d
0x6c617620 0x223d6575 0x646e6946 0x64692022
0x6966223d 0x625f646e 0x6f74746f 0x3c3e226d
0x726f662f 0x2f3c3e6d 0x0a3e696c 0x3c20200a
0x3c3e696c 0x6e617073 0x616c6320 0x223d7373
Leak: 0x19968200 size=1024
0x6d6c6f63 0x68697074 0x00000008 0x00000000
0x43fa8000 0x43ba0000 0x00000000 0x00000000
0x6b6d6f64 0x6d61676e 0x00000004 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000
0x77696e64 0x77696e64 0x00000004 0x00000000
0x776d6f75 0x68697074 0x00000008 0x00000000
0x43f60000 0x43aa8000 0x00000000 0x00000000
Leak: 0x20b1a200 size=1024
0x6d6c6f63 0x68697074 0x00000008 0x00000000

This one actually goes on for about 350,000 lines. I had been running this instance of Firefox for about an hour, but with a lot of tab use.

You can get stack frames and symbols in the stacks of leaked objects if you set environment variables that are explained in the man page.

I think there is a lot of room for improvement in controlling memory leaks.

There is actually much more I could say about this, but that is for another discussion. Really, I just wanted to say, here is a tool. It gives information. It is pretty accurate. If anyone has questions about using it, check the man page for the leaks executable, or feel free to ask me.


Johnath said...

Handy tip! I don't have my macbook up and running yet, but once I do I'll take a look.

If it helps track down the leaks, you could also take the output of this and pipe it through a perl one-liner like:

perl -e 'while(<>) { if(/^(\s+0x[0-9a-f]+){4}/) { s/[0x ]//g; s/([0-9a-f]{2})/chr(hex $1)/eg; print;}}'

...to see the ASCII version of the memory dumps. Obviously this will only help if the leaks are in code that handles text, but for ff or thunderbird that could be a significant percentage.

I was a little surprised that this option wasn't built into the tool, but maybe it is and the documentation I found was incomplete?

Will said...

I find MallocDebug a bit easier to handle than leaks. It wraps leaks but presents the leaks in a nice column interface allowing you to navigate to the leaked object and view how many times it has been leaked. Very handy!