_CrtDumpMemoryLeaks() and related fun

Welcome to the 1990s….

So, I have a new application that is resolutely non-MFC and non-ATL. Why? Because it's a GINA DLL that can be running on a machine going back to early 2001 (not quite the 1990s of the previous line but close enough!) where we have no idea whether it is running on XP SP0, SP1, SP2 or SP3.

This app has a lot of malloc and a lot of new object() calls in it. Are these all cleaning up after themselves?

Surprisingly(!), the C RunTime Library gives us an easy way to check; you can call _CrtDumpMemoryLeaks()

It ain't as easy as that though (obviously). To be effective, you need to bear in mind the following;

  1. _CrtDumpMemoryLeaks() only understands the context of its own module. Do you care? Well, if you are an EXE then possibly not, however you need to remember that _CrtDumpMemoryLeaks() only reports in leaks in its own module
  2. You need to set up the #defines before you start calling functions that will allocate memory. If you don't execute this step then you'll get a bunch of meaningless "static block at xxxxxx" messages with no easy way to identify the source
  3. This is the most important bit! _CrtDumpMemoryLeaks() does not report memory leaks (despite what it says on the tin). It reports the difference between the heap state on application (actually module) startup, and the current time

That last one keeps catching me out. I have spent way more time looking for alleged memory leaks, which are actually normal objects that have not yet been finalized, than I have on real memory leaks.

Let's take the following example;

"stdafx.h"

#include <crtdbg.h>

#include <string>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

wstring test = L"hello";

_CrtDumpMemoryLeaks();

return

 

 

0;

 

} 

This returns the following in the debug window;

 

 Detected memory leaks!

Dumping objects ->

{181} normal block at 0x00977F70, 8 bytes long.

Data: < 6 > E8 FE 36 00 00 00 00 00

Object dump complete.

The program '[8508] MemLeak.exe: Native' has exited with code 0 (0×0). 

 

 

Hold on! That's legal code! What went wrong?

Well, the problem is a common misunderstanding with _CrtDumpMemoryLeaks(). It actually shows the difference between the previous state (i.e. no objects defined on the heap) so the previous example is exactly correct; The wstring for "test" was still allocated so _CrtDumpMemoryLeaks() showed all outstanding allocations.

The solution to this is to ensure that all of your instantiated objects are released before calling _CrtDumpMemoryLeaks(). Obvious you may think, but there are two ways to do this.

The first is to declare everything as new / malloc and release before calling _CrtDumpMemoryLeaks(). The second, and easier to unit-test, is to encapsulate the core code and call _CrtDumpMemoryLeaks() after it completes.

These two methods are shown here;

 

 int _tmain(int argc, _TCHAR* argv[])

{

wstring *test = new wstring(L"hello");

delete test;

// We deleted all new'd allocations before checking

// for memory leaks

_CrtDumpMemoryLeaks();

return 0;

} 

 

 and my preference;

DoTheOperation(wchar_t *string);

int _tmain(int argc, _TCHAR* argv[])

{

DoTheOperation(L"hello");

// We deleted all new'd allocations before checking

// for memory leaks

_CrtDumpMemoryLeaks();

return 0;

}

void DoTheOperation(wchar_t *string)

{

printf("%s\n", string);

return;

} 

 

 So, in the latter of the two (and please accept my apologies for WordPress's crap syntax highlighting) we do all the dirty business in the called routines. The trick is to ensure that all allocated objects are released before you call _CrtDumpMemoryLeaks()

…and

Back to points 1) and 2)…

For one, you should ensure that you call _CrtDumpMemoryLeaks() in each module, as it is being released. For a DLL, this is the DllMain(DLL_PROCESS_DETACH) call.

And for #2, stick the following in your header file. To be honest, if you're including "stdafx.h" then that's a perfectly good place to put it;

 // stdafx.h : include file for standard system include files,

 

// or project specific include files that are used frequently, but

// are changed infrequently

//

#pragma once

// BEGIN Special Malloc Handling

#define _CRTDBG_MAP_ALLOC

#include <stdlib.h>

#include <crtdbg.h>

// END Special Malloc Handling

#include <stdio.h>

#include <tchar.h>

 

 

 

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <font color="" face="" size=""> <span style="">