42 out of 80 rated this helpful - Rate this topic

Memory Leak Detection Enabling 

This topic applies to:

Visual Studio Edition

Visual Basic

C#

C++

J#

Express

No

No

Native

No

Standard

No

No

Native

No

Pro/Team

No

No

Native

No

The primary tools for detecting memory leaks are the debugger and the C Run-Time Libraries (CRT) debug heap functions. To enable the debug heap functions, include the following statements in your program:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
NoteNote

The #include statements must be in the order shown here. If you change the order, the functions you use may not work properly.

By including crtdbg.h, you map the malloc and free functions to their debug versions, _malloc_dbg and _free_dbg, which keep track of memory allocation and deallocation. This mapping occurs only in a debug build (in which _DEBUG is defined). Release builds use the ordinary malloc and free functions.

The #define statement maps the base versions of the CRT heap functions to the corresponding debug versions. You do not absolutely need this statement, but without it, the memory leak dump will contain less useful information.

Once you have added the previous statements, you can dump memory leak information by including the following statement in your program:

_CrtDumpMemoryLeaks();

When you run your program under the debugger, _CrtDumpMemoryLeaks displays memory leak information in the Output window. The memory leak information looks like this:

Detected memory leaks!
Dumping objects ->
C:\PROGRAM FILES\VISUAL STUDIO\MyProjects\leaktest\leaktest.cpp(20) : {18} 
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.

If you do not use the #define _CRTDBG_MAPALLOC statement, the memory leak dump would look like this:

Detected memory leaks!
Dumping objects ->
{18} 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.

Without _CRTDBG_MAP_ALLOC defined, the display shows:

  • The memory allocation number (inside the curly braces).

  • The block type, which is normal, client, or CRT.

  • The memory location in hexadecimal form.

  • The size of the block in bytes.

  • The contents of the first 16 bytes, also in hexadecimal form.

With _CRTDBG_MAP_ALLOC defined, the display also shows you the file where the leaked memory was allocated. The number in parentheses following the file name (20, in this example) is the line number within the file.

To go to the line in the source file where the memory is allocated

  • Double-click on the line in the Output window that contains the file name and line number.

    -or-

    Select the line in the Output window that contains the file name and line number, and press F4.

_CrtSetDbgFlag

Calling _CrtDumpMemoryLeaks is easy enough if your program always exits in the same place. If your program can exit from multiple locations, instead of putting a call to _CrtDumpMemoryLeaks at each possible exit, you can include the following call at the beginning of your program:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

This statement automatically calls _CrtDumpMemoryLeaks when your program exits. You must set both bit fields, _CRTDBG_ALLOC_MEM_DF and _CRTDBG_LEAK_CHECK_DF, as shown previously.

Setting the CRT Report Mode

By default, _CrtDumpMemoryLeaks dumps memory leak information to the Debug pane of the Output window, as described previously. You can reset this to dump to another location using _CrtSetReportMode. If you use a library, it may reset the output to another location. In that case, you can set the output location back to the Output window using the following statement:

_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

For more information, see _CrtSetReportMode.

See Also

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
This is useless
If you need something that works without having to rewrite your project from zero I would recommend the "visual leak detector" (vld)

http://sites.google.com/site/dmoulding/vld

I tried the Microsoft solution and other solutions on the comments without any luck, the VLD got the memory leaks at the first build and fully detailed.
Additional suggestion regarding the #defines
The other comments are helpful, but I would add: the macros with DEBUG_NEW may need to be moved underneath your other #include statements to avoid conflicts.  Getting the line number information makes tracking down leaks much easier!
The reality is (like so often) different
One frustrating experience with MSFT documentation is realizing that in reality things just don't work as smoothly as one is made to believe. For example, tracking source lines through simply adding "#define _CRTDBG_MAP_ALLOC" is something that almost NEVER has worked for me, even though I have been trying this in my projects so many times. And then, each time I am left on my own to guess what could be wrong, since nobody responsible for this documentation seems to have tested this procedure under more complicated circumstances than what appears to be the most basic kind of application, which is probably some console .exe application. Also, a known bug that causes incorrect source lines to be reported (if at all), and which is also described in "Debugging Applications for Microsoft .NET and Microsoft Windows" by John Robbins is nowhere described in the official documentation. Is this one of the issues that MSFT so often refers to as "not a known issue"? I can hardly believe that those things have not already come to the attention of MFST.....

^^^
Probably the solution is to define _CRTDBG_MAP_ALLOC at project level or before #include lines. MFC coders often have stdafx.h file which include afx* headers, and one of them includes crtdbg.h where the compiler decides whether to use _malloc_dbg() with __FILE__ and __LINE__ info for malloc() calls. If #define _CRTDBG_MAP_ALLOC is placed in the target .cpp file, it is too late, as malloc() is already (pre-)compiled without file/line info. So define this symbol either in Project-->Settigns, or in the beginning of stdafx.h.
how to make it work vol. 2
I've been trying to make this detection work for a long time in my project and finally I was successful.

1) added _CRTDBG_MAP_ALLOC created to preprocessor definitions

2) created a file called debug.h containing:

#ifdef _DEBUG
#include <stdlib.h>
#include <crtdbg.h>

#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif

#endif

3) added include "debug.h" at the start of EACH .c file in my project

and now I can finally see the allocation places.

If anyone is able to force this debug to print a part of the stack trace, write here...
How to make it work

//--file1.c---
#define _CRTDBG_MAP_ALLOC //or in project Properties > Configuration Properties > C/C++ > Preprocessor > Preprocessor definitions > Append "_DEBUG; _CRTDBG_MAP_ALLOC"
#include <stdlib.h>
#include <crtdbg.h>
#include "file2.h"
int main(void)
{
char *a = NULL;
char *func_c_ptr = NULL;

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
_crtBreakAlloc = 52; //or 51 or 50 as show in the msg below>;
// Allocating memory here
a = (char*)malloc(10*sizeof(char));
/*func_b malloc but does not free the memory, hence leak*/
func_b();
/*func_c_ptr is not freed in any function hence the leak*/
func_c_ptr = func_c();

_CrtDumpMemoryLeaks();
return 0;
}


//--file2.c--
//#define _CRTDBG_MAP_ALLOC 
//#include <crtdbg.h>
#include <stdlib.h>
/*Dont free Mem in this function*/
void func_b(void)
{
char *ptr = (char*)malloc(120*sizeof(char));
}
/*Dont free Mem of this function*/
char* func_c(void)
{
char *ptr = (char*)malloc(130*sizeof(char));
return ptr;
}

//--file2.h--
//#define _CRTDBG_MAP_ALLOC
//#include <stdlib.h>
//#include <crtdbg.h>
extern void func_b(void);
extern char* func_c(void);


Detected memory leaks!
Dumping objects ->
{52} normal block at 0x00342CC0, 130 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
{51} normal block at 0x00342C08, 120 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
c:\file1.c(15) : {50} normal block at 0x00342BC0, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD 

A) If you include 
//#define _CRTDBG_MAP_ALLOC 
//#include <crtdbg.h>
in all the files, at the end of the debug run you can double click or press F4 on the output msg to take you code where the leaked memory was allocated

B) If you cannot or do not want to add those lines in every file... You can use "_crtBreakAlloc" as shown in file1.c to put a breakpoint on the memory allocation for next debug run. It is painful to be able to identify only one leak at a time this way, but atleast it works. 

What I know
MS formatting issue... Reposted later
Ah.. well.. it works.. iff..
I also struggled for a while with this issue.

I am using Visual Studio 2005. To get line-numbers and file-name for following example, I made some changes in project configuration. Lets first see the example:

#include "stdafx.h"

#include <stdlib.h>

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

{

// Allocating memory here
char *b = (char*)malloc(20);

char *a = new char[10];

char *c = (char*)malloc(20);

char *d = new char[10];

// Freeing some memory



delete a;

free(b);

return 0;

}


To get memory leak with file-name and line-number, I made following changes:
  1. In Project Properties > Configuration Properties > C/C++ > Preprocessor > Preprocessor definitions > Append _DEBUG; _CRTDBG_MAP_ALLOC;
  2. Add following lines in your source-file:
    • #include <stdlib.h>

      #include <crtdbg.h>

    • And after that, add following lines:

      #ifdef _DEBUG

      #define

      DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

      #define

      new DEBUG_NEW

      #endif

    • _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 

      in the beginning of your program.

So, your program should like after these modifications as:

#include "stdafx.h"

#include <stdlib.h>

#include <crtdbg.h>


#ifdef _DEBUG

#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

#define new DEBUG_NEW

#endif

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

{


_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );


char *b = (char*)malloc(20);

char *a = new char[10];

char *c = (char*)malloc(20);

char *d = new char[10];


delete a;

free(b);


return 0;

}


When you run this program, you should see leaks-report as:

c:\documents and settings\csingh\my documents\visual studio 2005\projects\leak\leak\leak.cpp(23) : {109} normal block at 0x0035B928, 10 bytes long.

Data: < > CD CD CD CD CD CD CD CD CD CD

c:\documents and settings\csingh\my documents\visual studio 2005\projects\leak\leak\leak.cpp(22) : {108} normal block at 0x0035B8D8, 20 bytes long.

Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

Hope that it Helps!!!
-Chandan
file name and line number not work for vs2005

this will not show file name and line number in the output, vs2005, no idea what is wrong

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#define NUM_PTRS 5
#define MEM_SIZE 150
void* g_ptrs[NUM_PTRS];
UINT thread_malloc(LPVOID param)
{
for(int i = 0; i < NUM_PTRS; i++)
{
g_ptrs[i] = malloc(MEM_SIZE);
memset(g_ptrs[i], 0, MEM_SIZE);
}
return 0;
}
void Cmalloc_thread_testDlg::OnBnClickedButton1()
{
AfxBeginThread(thread_malloc, NULL);
}

void Cmalloc_thread_testDlg::OnBnClickedButton3()
{
_CrtDumpMemoryLeaks();
}

When using free/malloc/realloc it's ok, but how find leak for new and delete ?
When using free/malloc/realloc it's ok,

but how find leak for new and delete in the same way ?

I find this : (http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2931462&SiteID=1)

// compile with cl /D_DEBUG /MDd /EHsc leak2.cpp

#define

_CRTDBG_MAP_ALLOC

#include

<iostream>

#include

<crtdbg.h>

#ifdef

_DEBUG

#define

DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

#define

new DEBUG_NEW

#endif

int

main()

{

char *a = newchar[10]; char *b = (char*)malloc(20);

_CrtDumpMemoryLeaks();

return 0;

}

Recommendation - Use the _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ) method
CAUTION!

When using the method of including the call

_CrtDumpMemoryLeaks();

just before your program exits, remember that the destructors for any variables you declared at runtime (i.e. any variables declared not using the 'new' operator) have *NOT* been called yet. This makes the memory holding these variables look like leaked memory when in fact the memory will be cleaned up just prior to program exit.

For this reason, I highly recommend that you use the other method described, i.e. the first line of your main() function reads


_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

This allows you to not have to worry about covering all your program exits with a call to _CrtDumpMemoryLeaks() and also allows for calls to destructors before testing for memory leaks.


I think it was somewhat irresponsible to leave this information out of this article - it seems pretty fundamental to the concept of leak detection. If anything, the _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ) should have been listed first...


Good luck!

  • 4/17/2008
  • WDA
Advertisement