Debugging Memory Leaks, Part 2: CRT support

This feature is well documented, but yet from what I see – doesn’t get the usage it deserves. Here’s a quick, beginner-oriented rehash – if only to refer my teammates.

Problem and Immediate Solution

If you’re developing MFC apps, the way you’ll usually notice any leaks is by terminating your app and seeing the following in the output window:

Detected memory leaks!
Dumping objects ->
C:\myfile.cpp(20): {130} normal block at 0x00780E80, 64 bytes long.
Data: <      > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

the {130} is emphasized on purpose – it is the serial number of the leaking allocation.  What if you could count allocation occurrences, and break in exactly the leaky one?  You could not only get a complete stack trace for the leak, but even step and debug it!

Well, it might not be that easy.  If the allocation serial number is not consistent across multiple runs, it means the leaking memory is allocated in a threaded code portion.  In such cases, you’re probably better off resorting to other methods.

Now if the serial number is consistent, what allocations exactly does it count? In what API do you brake??  must you really set a breakpoint with a ‘hit count’ there?  If the number is high, it could easily get prohibitively slow.

Happily, there is an easy solution to the second set of worries. Early in your code, call –

_CrtSetBreakAlloc(130)

Mid-depth Dive

The _CrtSetBreakAlloc trick is an iceberg-tip of some heavier CRT machinery. It is entirely operated for you if you use MFC, but you can use it yourself in non-MFC apps (although you should watch out for some issues).

The dump that starts it all is the output of _CrtDumpMemoryLeaks.  You can call it directly in your app – but if you’re down to a binary search for the leak , you  might prefer _CrtMemDumpAllObjectsSince for more fine-grained control of the allocations you dump. Maybe more on that in a future post.

The allocation counter resides in the undocumented _heap_alloc_dbg, which channels calls from all C allocators – namely new, malloc, and their brethren (_malloc_dbg, aligned /offset flavours, etc.).  This is a CRT apparatus, so naturally it won’t catch direct OS allocations (HeapAlloc, VirtualAlloc et. al.), not to mention COM allocators (SysAllocString, CoTaskMemAlloc etc.).

When you do set an allocation breakpoint, you’d (naturally) break in the counting function itself, _heap_alloc_dbg.  Your own code probably resides a good 4-5 stack levels below – go there and debug away.

Bonus

You can do all the above at runtime, from the debugger. The documentation for VS2005 says you can put –

{,,msvcr71d.dll}_crtBreakAlloc

in the watch window, and modify its contents directly (say, to 130). However, the documentation is wrong in 3 places.

  1. For VS2005, the correct dll version is msvcr80d.dll. This seems to have been fixed for the VS2008 and VS2010 pages.
  2. When using the context operator, you must use decorated symbol names – which amounts to adding another underscore.
  3. The value is an int*, and for some reason my debugger fails to deduce it himself.

All in all, just type at the watch window –

(int*){,,msvcr80d.dll}__crtBreakAlloc

And debug happily ever after.

Digg This
Advertisements
This entry was posted in Debugging, VC++. Bookmark the permalink.

3 Responses to Debugging Memory Leaks, Part 2: CRT support

  1. Alan Ning says:

    I have been pondering on that serial number for quite a few years, and new found a good tutorial on it.

    This really solves a lot of mysteries.

    Thanks for the article.

  2. Pingback: Debugging Memory Leaks, Part 3: Breaking on Allocations of Given Size « Ofek's Visual C++ stuff

  3. Pingback: Debugging Reference Count – Part 1 « Ofek's Visual C++ stuff

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s