Although the concept has been too much to say, still want to record briefly, for later query.
#ifdef _DEBUG
#define Debug_clientblock New (_client_block, __file__, __line__)
#else
#define Debug_clientblock
#endif
#define _crtdbg_map_alloc
#include <crtdbg.h>
#ifdef _DEBUG
#define NEW Debug_clientblock
#endif
int _tmain (int argc, _tchar* argv[])
{
char* p = new char ();
char* pp = new char[10];
char* PPP = (char*) malloc (10);
_CrtDumpMemoryLeaks ();
return 0;
}
The main principle is to use the CRT's memory debugging function, replace the default operator new with a macro, let it be replaced by the following version:
void *__crtdecl operator New (
size_t CB,
int Nblockuse,
const char * szFileName,
int NLine
)
_throw1 (_STD bad_alloc)
{
/* _nh_malloc_dbg already calls _heap_alloc_dbg in a loop and calls _CALLNEWH
If the allocation fails. If _CALLNEWH returns (very likely because no
New handlers has been installed by the user), _NH_MALLOC_DBG returns NULL.
*/
void *res = _nh_malloc_dbg (CB, 1, Nblockuse, szFileName, nLine);
Rtccallback (_rtc_allocate_hook, (res, CB, 0));
/* If the allocation fails, we throw std::bad_alloc */
if (res = = 0)
{
static const Std::bad_alloc NOMEM;
_raise (NOMEM);
}
return res;
}
In this way, the CRT will record the file name and line number and size of the allocated memory, and finally when the call with _CrtDumpMemoryLeaks (); It will print out if it is not released.
The results are as follows:
Detected memory leaks!
Dumping objects
F:\test\memleakchecker\memleakchecker\memleakchecker.cpp: {108} normal block at 0x0003a1a8, bytes long.
Data: < > CD CD CD CD CD CD CD
F:\test\memleakchecker\memleakchecker\memleakchecker.cpp: {107} client block at 0x0003a160, subtype 0, Bytes long .
Data: < > CD CD CD CD CD CD CD
F:\test\memleakchecker\memleakchecker\memleakchecker.cpp: {106} client block at 0x0003a120, subtype 0, 1 bytes long.
Data: < > 00
Object dump complete.
Here are some things to note:
(1) Role of #define _crtdbg_map_alloc
If you do not define this macro, the C-mode malloc leak is not recorded.
(2) The role of the number {108} {107}
Indicates the number of allocations, which you can pause by _CrtSetBreakAlloc the program to the scheduled times, such as
int _tmain (int argc, _tchar* argv[])
{
_CrtSetBreakAlloc (108);
char* p = new char ();
char* pp = new char[10];
char* PPP = (char*) malloc (10);
_CrtDumpMemoryLeaks ();
return 0;
}
(3) If the program has multiple exits or if there are global variables, you can use the _CrtSetDbgFlag set flag to let the program exit automatically print leaks, such as
int _tmain (int argc, _tchar* argv[])
{
_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _crtdbg_leak_check_df);
char* p = new char ();
char* pp = new char[10];
char* PPP = (char*) malloc (10);
return 0;
}
(4) We know that macro substitution is the most brutal way, so try to put the following new substitution macro in each CPP instead of a generic header file, which is actually what MFC does.
#ifdef _DEBUG
#define NEW Debug_clientblock
#endif
(5) The above operator new can only take care of the most common new, in fact operator new is any number of overloaded methods, just to ensure that the first parameter is a representation of size. For example, the following placement new will fail to compile because the macro substitution format does not meet the requirements, so if your CPP uses non-standard new, do not add new detection macros.
#include <new>
#ifdef _DEBUG
#define Debug_clientblock New (_client_block, __file__, __line__)
#else
#define Debug_clientblock
#endif
#define _crtdbg_map_alloc
#include <crtdbg.h>
#ifdef _DEBUG
#define NEW Debug_clientblock
#endif
int _tmain (int argc, _tchar* argv[])
{
_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _crtdbg_leak_check_df);
char* p = new char ();
char* pp = new char[10];
char* PPP = (char*) malloc (10);
Char D;
char* p1 = new (&d) char (' a ');
return 0;
}
(6) because the tree in the STL map uses the placement new, if you use this, it will fail to compile:
#ifdef _DEBUG
#define Debug_clientblock New (_client_block, __file__, __line__)
#else
#define Debug_clientblock
#endif
#define _crtdbg_map_alloc
#include <crtdbg.h>
#ifdef _DEBUG
#define NEW Debug_clientblock
#endif
#include <map>
You should put #include <map> in front of the macro definition.
(7) If you declare or define the operator new function after the macro #define new Debug_clientblock, the compilation will fail because of the macro substitution.
The STL Xdebug file exactly declares the operator new function, so make sure that the replacement macro for new is placed at the end of all include header files, especially after the STL header file.
Myclass.cpp#include "Myclass.h"
#include <map>
#include <algorithm>
#ifdef _DEBUG
#define NEW Debug_clientblock
#endif
Myclass::myclass ()
{
char* p = new char (' a ');
}
(8) If you think that the above new substitution macro scattered in the various CPP too troublesome, want to put everything in a generic header file, please refer to the following definition of the way:
MemLeakChecker.h
#include <map>
#include <algorithm>
Other STL file
#ifdef _DEBUG
#define Debug_clientblock New (_client_block, __file__, __line__)
#else
#define Debug_clientblock
#endif
#define _crtdbg_map_alloc
#include <crtdbg.h>
#ifdef _DEBUG
#define NEW Debug_clientblock
#endif
(9) Simple to determine whether a separate function memory leaks can be used in the following way:
Class Dbgmemleak
{
_CrtMemState M_checkpoint;
Public
Explicit Dbgmemleak ()
{
_CrtMemCheckpoint (&m_checkpoint);
};
~dbgmemleak ()
{
_CrtMemState checkpoint;
_CrtMemCheckpoint (&checkpoint);
_CrtMemState diff;
_CrtMemDifference (&diff, &m_checkpoint, &checkpoint);
_CrtMemDumpStatistics (&diff);
_CrtMemDumpAllObjectsSince (&diff);
};
};
int _tmain (int argc, _tchar* argv[])
{
Dbgmemleak check;
{
char* p = new char ();
char* pp = new char[10];
char* PPP = (char*) malloc (10);
}
return 0;
}
(10) Actually know the principle, write a set of C + + memory leak detection is not difficult, mainly heavy load operator new AND operator delete, you can record each memory allocation situation in a map, delete deleted records, When the program exits, it prints the map without the delete. Of course, we know that the CRT in the implementation of new is generally the actual tune of malloc, and malloc may be the tune HeapAlloc, and HeapAlloc may be called rtlallocateheap, so theoretically we can intercept and record at any level of these functions. But if you want to implement your own cross-platform memory leak detection, reload operator new.
Http://www.cppblog.com/weiym/archive/2013/02/25/198072.html
CRT-based memory leak detection in C + + (reload new and delete, recorded in map)