此文章针对控制台与win32项目
我以Windows下visual studio为例解释步骤
1.在stdafx.h头文件中添加以下代码
#include <crtdbg.h>
#ifdef _DEBUG
#define DEBUG_NEW new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_NEW
#endif
#define _CRTDBG_MAP_ALLOC
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
2.当然你也可以将上面的内容缩减为下面这样:
#include<crtdbg.h>
#ifdef _DEBUG
#define new new(_CLIENT_BLOCK, __FILE__, __LINE__)
#define _CRTDBG_MAP_ALLOC
3.要使用vc提供的内存泄露查找功能还需要在你的入口点函数中添加下面这句
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF) ;
以下贴出msdn对以上两个标志的解释:
_CRTDBG_ALLOC_MEM_DF
ON: Enable debug heap allocations and use of memory block type identifiers, such as_CLIENT_BLOCK. OFF: Add new allocations to heap's linked list, but set block type to_IGNORE_BLOCK.
Can also be combined with any of the heap-frequency check macros.
_CRTDBG_LEAK_CHECK_DF
ON: Perform automatic leak checking at program exit through a call to _CrtDumpMemoryLeaks and generate an error report if the application failed to free all the memory it allocated. OFF: Do not automatically perform leak checking at program exit.
Can also be combined with any of the heap-frequency check macros.
4.对上面的内容做些简单解释
上面对new的宏扩展与_CRTDBG_MAP_ALLOC的定义分别是为了使用调试模式的new与malloc。
调试模式下的new与malloc可以定位内存泄露的文件名与行号,便于查找调试。
(1).经过扩展后,new调用的就变为dbgnew.cpp文件中的下面这个函数
void *__CRTDECL operator new(
size_t cb,
int nBlockUse,
const char * szFileName,
int nLine
)
_THROW1(_STD bad_alloc)
这样当你调用new int ;的时候实际上就是调用了new(_CLIENT_BLOCK, __FILE__, __LINE__) int ;即对应于上面的那个函数。
这种new的语法形式好像和普通的重载不太一样。嗯,我也不太懂,这大概是new的特殊方式吧。。。望高人指点
这里再说一下_CLIENT_BLOCK,这个是内存块类型。有以下几种:
/* Memory block identification */
#define _FREE_BLOCK 0
#define _NORMAL_BLOCK 1
#define _CRT_BLOCK 2
#define _IGNORE_BLOCK 3
#define _CLIENT_BLOCK 4
#define _MAX_BLOCKS 5
详见:http://msdn.microsoft.com/zh-cn/library/htdyz80k.aspx
(2).当你调用malloc时,就直接调用下面函数了:
extern "C" _CRTIMP void * __cdecl _malloc_dbg (
size_t nSize,
int nBlockUse,
const char * szFileName,
int nLine
)
该函数位于dbgheap.c中
这次是因为定义了_CRTDBG_MAP_ALLOC这个常量后,在crtdbg.h文件中有一个宏扩展。如下图:
5.最后有可能在编译时出现警告,如下图:
这个原因编译器写的很清楚了,所以我们能做的就是根据自己的需要注释掉会产生问题的文件
举例:想在调试模式检查内存泄露,可以选择注释掉malloc.h文件
不想检测malloc产生的内存泄露位置,可以选择注释掉_CRTDBG_MAP_ALLOC这个常量定义