Sunday, 1 August 2010

Memory Leaks

Yesterday, I spent some time trying to fix any memory leak I could find. This is the kind of things that I like to check regularly as it is a massive pain when you do it after it's not been done in a while. More importantly, leaks are often a good indicator that areas of code require more design and code quality attention so that's always worth keeping an eye on that.

There are several ways to track memory leaks and there is already a lot of tools available and web articles on this subject. I will probably have a look at more advanced solutions in the future but for this session I used a really basic yet powerful method. The CRT library that ships with Visual Studio has some debug functionality to help track leaks down. Basically the allocator can track all the allocations that were made and that were not deallocated before exiting the application. This is done by adding a single line at the very beginning of your entry point function (you can put it anywhere really but you really want that call to happen as early as possible so you can start tracking allocations):

_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

If you happen to have memory leaks, after closing the app, you should see in the Output window of Visual Studio something that looks like that:

Detected memory leaks!
Dumping objects ->
{2221} normal block at 0x08FE63D0, 164 bytes long.
 Data: <                > D4 88 1A 10 FF FF FF FF FF FF FF FF 00 00 00 00
{2191} normal block at 0x090771C8, 164 bytes long.
 Data: <                > D4 88 1A 10 FF FF FF FF FF FF FF FF 00 00 00 00
{2079} normal block at 0x09077590, 164 bytes long.
 Data: <                > D4 88 1A 10 FF FF FF FF FF FF FF FF 00 00 00 00
{2047} normal block at 0x08FD9918, 164 bytes long.
 Data: <                > D4 88 1A 10 FF FF FF FF FF FF FF FF 00 00 00 00
{469} normal block at 0x08FE5F98, 164 bytes long.
 Data: <                > D4 88 1A 10 FF FF FF FF FF FF FF FF 00 00 00 00
Object dump complete.

This is the list of all the allocated memory blocks that were not deallocated. Notice the number in the brackets at the beginning of every block - that's where things get interesting :) This number is an identifier for this particular memory allocation. The good thing is that there is another function you can use at the very beginning of your app to break into the debugger whe
n that specific allocation happens, so you can work out why there is no deallocation and fix the issue :

_CrtSetBreakAlloc( 2221 ); // Breaks in the debugger when alloc id=2221 is made !

This is not as lean as using some tools like BoundsChecker or more advanced debug functionnality you can embed in your software but it comes out of the box - on windows at least. I find that if you have it turned on all the time and regularly check your log output, then you can fix the leaks as soon as they appear and keep an application that is stable memorywise.

2 comments:

  1. I use VLD for catching memory leaks. It's a simple wrapper for the VC++ CRT, but all you have to do is #include 〈vld.h〉 somewhere in your program.

    If it detects leaks on quit (with the debugger attached), it'll dump a report in the output window containing what leaked, how much, and a full callstack with the offending call to "new" at the top. As a bonus, the output is clickable in the same way as the compile errors/warnings are :)

    ReplyDelete
  2. Sounds pretty awsome. I'll give it a try, especially if the integration is that easy. Thanks!

    ReplyDelete