Learning Paradigm Http://www.cppblog.com/Robertxiao/archive/2012/11/05/194547.html
When using the MFC library developer, I love the memory leak diagnostic mechanism in the MFC framework, which really helps us to find out the memory leaks. But the link to the MFC library also makes the resulting executable file a lot larger, this has no negative impact.
The scariest thing is that if you're only using the memory diagnostic mechanism, it's a hassle to link library conflicts. I also encountered this problem, only to write a simple memory diagnostic mechanism.
It is generally assumed that these memory leak detection features are provided by MFC, but it is not. MFC simply encapsulates and leverages the debug Function of the MS C-runtime Library.
Non-MFC programs can also use the MS C-runtime Library's debug function to add memory leak detection. The MS C-runtime Library has built in memory leak detection functions when implementing functions such as Malloc/free,strdup.
Notice the project generated by the MFC Application Wizard, which has a macro definition in the head of each CPP file:
#ifdef _DEBUG #define NEW Debug_new #undef This_file static char this_file[] = __file__; #endif |
With this definition, all new files appearing in this CPP file are replaced with Debug_new when compiling the debug version. So what is Debug_new? Debug_new is also a macro, the following excerpt from afx.h,1632 line
#define DEBUG_NEW NEW (This_file, __line__) |
So if there's a line of code like this:
After the macro substitution, it becomes:
char* p = new (This_file, __line__) char[200]; |
According to the standard of C + +, for the use of the new method above, the compiler will look for the definition of operator NEW:
void* operator New (size_t, LPCSTR, int) |
We found an implementation of this operator new in Afxmem.cpp 63.
void* afx_cdecl operator New (size_t nSize, LPCSTR lpszfilename, int nLine) { Return:: operator new (NSize, _normal_block, lpszFileName, nLine); } void* __cdecl operator New (size_t nSize, int nType, LPCSTR lpszfilename, int nLine) { ... PResult = _malloc_dbg (NSize, NType, lpszFileName, nLine); if (pResult! = NULL) return pResult; ... } |
The second operator new function is longer, and for the sake of simplicity, I only excerpt the part. It is clear that the last memory allocation is still implemented through the _MALLOC_DBG function, which belongs to the debug function of the MS C-runtime Library. This function requires not only the size of the incoming memory, but also the file name and line number two parameters. The file name and line number are used to record which piece of code is responsible for this assignment. If there is no release before the program ends, the information is exported to the Debug window.
Here by the way This_file,__file and __line__. Both __file__ and __line__ are compiler-defined macros. When __FILE__ is encountered, the compiler replaces __file__ with a string that is the path name of the currently compiled file. When __LINE__ is encountered, the compiler replaces the __line__ with a number, which is the line number of the current line of code. Instead of using __file__ directly in the definition of debug_new, this_file is used to reduce the size of the target file. Assuming that there are 100 uses of new in a CPP file, if you use __file__ directly, the compiler will produce 100 constant strings, and the 100 strings are the path names of the supper./span>cpp file, which is clearly redundant. If you use This_file, the compiler produces only a constant string, and the 100 new call uses a pointer to a constant string.
Looking again at the project generated by the MFC Application Wizard, we will find that only new mappings are made in the CPP file, and if you use the malloc function to allocate memory directly in your program, the file name and line number of the call to malloc will not be recorded. If this memory leaks, the MS C-runtime Library can still detect, but when the output of this block of memory information, it will not contain the file name and line number assigned to it.
To open the memory leak detection feature in a non-MFC program is very easy, just add the following lines of code at the entrance to the program:
int tmpflag = _CrtSetDbgFlag (_crtdbg_report_flag); Tmpflag |= _CRTDBG_LEAK_CHECK_DF; _CrtSetDbgFlag (Tmpflag); |
Thus, at the end of the program, when the Winmain,main or DllMain function returns, their information will be printed to the debug window if the memory blocks are not released.
If you try to create a non-MFC application and add the above code at the entrance to the program and intentionally do not release some memory blocks in the program, you will see the following information in the Debug window:
{0X00C91C90} normal block at bytes long. Data: < > Geneva, Geneva, 0A 0B 0C 0D 0E 0F |
The memory leak was detected, but the file name and line number were missing compared to the example of the MFC program above. For a larger program, without this information, solving the problem will become very difficult.
In order to be able to know where the leaking memory blocks are allocated, you need to implement a mapping function similar to MFC and map New,maolloc functions to the _malloc_dbg function. I will not repeat here, you can refer to the source Code of MFC.
Because the debug function is implemented in MS C-runtimelibrary, it detects only the leak of the heap memory and is limited to allocated memory such as Malloc,realloc or strdup, and those system resources, such as Handle,gdi Object, or the memory that is not allocated through the C-runtime library, such as variant,bstr leaks, is undetectable and is a significant limitation of this detection method. In addition, in order to be able to record where the memory block is allocated, the source code must match, which in debugging some of the old program is very troublesome, after all, modify the source code is not a worry, this is another limitation of this detection method.
//header File#pragmaOnce#include<crtdbg.h>#include<malloc.h>#ifdef _DEBUG#defineThis_file __file__//add a macro definition, memory leaks can also be detected by allocating memory with malloc#definemalloc (s) _malloc_dbg (S, _normal_block, __file__, __line__)//setting use new to allocate memory to detect a memory leakvoid* _CDECLoperator New(size_t nSize,intNType,Const Char* lpszFileName,intnLine);//overwrite the operator new and delete operators,void* _CDECLoperator New(size_t nSize,Const Char* lpszFileName,intnLine);void* __cdecloperator New[] (size_t nSize,Const Char* lpszFileName,intnLine);void__cdecloperator Delete(void*p);void__cdecloperator Delete[](void*p);#defineDebug_new NEW (This_file, __line__)#else#defineDebug_new NEW#endif //_DEBUG//definitions for new overrides in MFC's Afx.h header file//Memory Tracking Allocation//void* afx_cdecl operator new (size_t nSize, LPCSTR lpszfilename, int nLine);//#define DEBUG_NEW NEW (This_file, __line__)//void afx_cdecl operator delete (void* p, LPCSTR lpszfilename, int nLine);////void * __cdecl operator new[] (size_t);//void* __cdecl operator new[] (size_t nSize, LPCSTR lpszfilename, int nLine);//void __cdecl operator delete[] (void* p, LPCSTR lpszfilename, int nLine);//void __cdecl operator delete[] (void *);
//implementation file//#include "StdAfx.h"#include <malloc.h>#include"DebugNew.h"namespace{ classAutodetectmemory { Public: Autodetectmemory () {#ifdef _DEBUG _CrtSetReportMode (_crt_error, _crtdbg_mode_debug); _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);#endif } }; Staticautodetectmemory gs_am;}void* _CDECLoperator New(size_t nSize,Const Char* lpszFileName,intnLine) { return::operator New(NSize, _normal_block, lpszFileName, nLine);}void* __cdecloperator New[] (size_t nSize,Const Char* lpszFileName,intnLine) { return::operator New(NSize, _normal_block, lpszFileName, nLine);}void__cdecloperator Delete(void*p) {#ifdef _DEBUG _free_dbg (P, _normal_block);#else Free(p);#endif}void__cdecloperator Delete[](void*p) { ::operator Delete(P);}void* __cdecloperator New(size_t nSize,intNType,Const Char* lpszFileName,intnLine) {#ifdef _DEBUGreturn_malloc_dbg (nSize, NType, lpszFileName, nLine);#else //Unreferenced_parameter (NType); //Unreferenced_parameter (lpszFileName); //Unreferenced_parameter (nLine); return::operator New(nSize);#endif}
Test results:
How to use:
Include header files in stdafx.h
Add the following code to the file where you want to use the diagnostic mechanism.
#ifdef _DEBUG
#define NEW Debug_new
#endif
This allows the memory leak to be applied to the new application, or the memory leak from malloc to be output in the Debug window after the program exits gracefully. The full file path, number of rows, and number of leaked bytes are displayed.
Learn to build your own debug_new