今天写一个程序突然想检测一下是否有内存泄漏,于是上网查了一下,大多数都是一种方法。只是实现略有不同,记录如下。
在你想检测的地方都必须包含
#define _CRTDBG_MAP_ALLOC
#include
#include
在程序末尾加上_CrtDumpMemoryLeaks()
Debug调试后,如果有内存泄漏,调试窗口会输出内存泄漏的块,如下:
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOOC
#include
#include
int _tmain(int argc, _TCHAR* argv[])
{
{
int *b = new int;
}
{
char *b = new char[100];
}
_CrtDumpMemoryLeaks();
return 0;
}
调试输出:
会提示一个块号和泄漏的大小。代码中加大括号的目的是说明指针的作用域,超出作用域还未释放自然就是泄漏。所以一般全局变量分配了内存,到程序结束时候才释放,但此函数会一直把新申请的内存当作泄漏来对待。所以最好别再全局分配。
在程序入口写几个语句,程序退出时,如果发现有内存泄漏,会自动在DEBUG OUTPUT窗口和DebugView中输出内存泄漏信息。
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag( tmpFlag );
代码如下:
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOOC
#include
#include
int _tmain(int argc, _TCHAR* argv[])
{
int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(tmpFlag);
{
int *a= new int;
}
{
char *b = new char[100];
}
//_CrtDumpMemoryLeaks();
return 0;
}
结果是一样的,就不展示。
使用_CrtMemCheckpoint(),可以查出某程序段的内存泄漏情况。如下:
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOOC
#include
#include
int _tmain(int argc, _TCHAR* argv[])
{
//int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
//tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
//_CrtSetDbgFlag(tmpFlag);
_CrtMemState s1, s2, s3;
_CrtMemCheckpoint(&s1);
{
int *a= new int;
}
{
char *b = new char[100];
}
_CrtMemCheckpoint(&s2);
if (_CrtMemDifference(&s3, &s1, &s2)) _CrtMemDumpStatistics(&s3);
//_CrtDumpMemoryLeaks();
return 0;
}
知道了发生内存泄漏的块号,可以使用_CrtSetBreakAlloc();函数在块号处中断,程序入口中加上_CrtSetBreakAlloc(块号),debug后中断的地方就是分配内存未释放的地方。
通过一系列宏定义可以直接得到内存泄漏的代码行数。实例如下:
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOC
#include
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif // _DEBUG
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif // _DEBUG
int *p = new int;
int _tmain(int argc, _TCHAR* argv[])
{
{
int *a = new int;
}
{
char *b = new char[100];
}
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
return 0;
}