Valgrind for Mac OS X – first impressions

Not so long ago, Apple developer Greg Parker, published a patch for a specific revision of Valgrind so that it can work in Mac OS X. You can check the details of how to install it in his webpage, it doesn’t take more than 5 minutes to do it:

I made a simple test to see how well or bad it works, with definitely lost and still reachable memory leaks. The test goes as follows:

#include <stdio.h>
#include <string.h>
/* Global string, still-reachable */
static char *global_str;
int main(int argc, char **argv)
  /* Function-local string,
   * definitely-lost */
  char *str = NULL;
  /* These are 10+1 bytes leaked */
  str = strdup("1234567890");
  /* These are 15+1 bytes leaked */
  global_str = strdup("123456789012345");
  return 0;

We compile it…

$> gcc -o test test.c

Now, let’s see if this valgrind port catches our memory leaks.

$> valgrind --show-reachable=yes --leak-check=full --leak-resolution=high ./test

Well, valgrind runs and we start checking its output:

==13340== LEAK SUMMARY:
==13340== definitely lost: 11 bytes in 1 blocks.
==13340== possibly lost: 0 bytes in 0 blocks.
==13340== still reachable: 316 bytes in 8 blocks.
==13340== suppressed: 0 bytes in 0 blocks.

We were only expecting 11 bytes definitely lost (local-function pointer) and 16 bytes still reachable (global pointer), but we have lots more still reachable. Let’s see the detailed results:

==13340== ERROR
==13340== 11 bytes in 1 blocks are definitely lost in loss record 1 of 4
==13340== at 0x22E53: malloc+99 (in /usr/local/lib/valgrind/x86-darwin/
==13340== by 0x21A3D1: strdup+33 (in /usr/lib/libSystem.B.dylib)
==13340== by 0x1FBB: main+33 (in ./test)
==13340== ERROR
==13340== 16 bytes in 1 blocks are still reachable in loss record 2 of 4
==13340== at 0x22E53: malloc+99 (in /usr/local/lib/valgrind/x86-darwin/
==13340== by 0x21A3D1: strdup+33 (in /usr/lib/libSystem.B.dylib)
==13340== by 0x1FCC: main+50 (in ./test)

Ok, here are our memory leaks. Let’s see what is the other stuff.

==13340== ERROR
==13340== 60 bytes in 1 blocks are still reachable in loss record 3 of 4
==13340== at 0x22E53: malloc+99 (in /usr/local/lib/valgrind/x86-darwin/
==13340== by 0x1F7E89: get_or_create_key_element+157 (in /usr/lib/libSystem.B.dylib)
==13340== by 0x1F7DBB: _keymgr_get_and_lock_processwide_ptr_2+21 (in /usr/lib/libSystem.B.dylib)
==13340== ERROR
==13340== 240 bytes in 6 blocks are still reachable in loss record 4 of 4
==13340== at 0x24DD9: calloc+105 (in /usr/local/lib/valgrind/x86-darwin/
==13340== by 0x1F79D9: dwarf2_unwind_dyld_add_image_hook+40 (in /usr/lib/libSystem.B.dylib)
==13340== by 0x8FE03D61: dyld::registerAddCallback(void (*)(mach_header const*, long))+145 (in /usr/lib/dyld)

As expected (Greg already warned about it) we are getting some leak reports of system libraries, as being still reachable. The “still reachable” means that when the program ended some allocations were done previously using pointers that are ‘global’ to the program, so still reachable when program ended. In other words, valgrind found pointers to allocated memory in the context when the program ended, and the only context available in that time is the global one. All the other contexts (different functions called, even main()) dissappear when the program ends, and pointers declared in those functions which are used to allocate memory are the “definitely lost” ones.

Well, I would say that there is still work to be done, but I don’t see having these system library allocation leak reports a real problem. Once you have linked your programs against Glib, you will get used to see this kind of error reports, but multiplied by 1000. Glib does lots of memory allocations in g_type_init() that are not deallocated with a g_type_deinit() (there is no such function), so they are deallocated by the OS when the program ends. To deal with the ones from Glib, it’s usual to skip using
leak-resolution=high and use Valgrind suppression files.

Probably these reported errors are not comparable to the ones from Glib, but the way to deal with them should be really similar. So, good job Greg! and let’s see if this port can be improved until it’s completely included in Valgrind sources.


Posted on September 30, 2008, in Development, Operating Systems and tagged , , . Bookmark the permalink. 2 Comments.

  1. Expect –show-reachable to be uselessly noisy, especially if you use any higher-level frameworks. This is true on pretty much any platform, because cleaning up still-reachable memory during exit is a waste of CPU time.

    For leak checking on Mac OS X, I’d recommend the `leaks` tool and the memory analysis in Instruments. They’re on par with Valgrind’s leak checking, and run much faster. Valgrind is best for tracking other memory errors like uninitialized values and buffer overruns.

  2. Hi Greg, nice to see you here. Also wrote to you in the valgrind-dev mailing list.

    Truth be told, never used `leaks’. I’ll try it. Anyway, that was an impressive job. I also tried to port it to MacOSX some time ago, but completely gave up.

    Would be nice to have it included in Valgrind repo some day.

    Cheers and congrats!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: