C++检测和定位内存泄漏
1、首先需要宏定义一下new运算符
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif // DEBUG
解释:
new(a, b, c) T;
会被解释成一个函数调用operator new(sizeof(T), a, b, c)。这是C++就有的行为 operator new, operator new[],user-defined placement allocation functions。这里就是把那几个参数传给重载的operator new,这样可以在operator new里面记录下来 _NORMAL_BLOCK, __FILE__, __LINE__,调试的时候就能看到是在哪里new的。
_NORMAL_BLOCK
mingw-w64 的 crtdbg.h 里这个宏展开成整数 1 。意味着分配 1 个对象的内存。
__FILE__
文件名
__LINE__
第几行
2、控制调试堆管理器 (仅限调试版本) 的分配行为
//程序开始就调用一下这个函数
void EnableMemLeakCheck()
{
int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(tmpFlag);
}
//函数原型 int _CrtSetDbgFlag( int newFlag);
参数
newFlag
新状态的_crtDbgFlag。
返回值
返回的前一状态_crtDbgFlag。
备注
_CrtSetDbgFlag函数允许应用程序来控制调试堆管理器通过修改的位域跟踪内存分配的方式_crtDbgFlag标志。 通过设置位(打开),该应用程序可指示调试堆管理器执行特殊的调试操作,包括在应用程序退出时检查内存泄露并报告是否找到任何内存泄露、通过指定已释放的内存块应保留在堆的链接列表中来模拟内存不足情况,以及通过在每次分配请求时检查每个内存块来验证该堆的完整性。 当 _DEBUG未定义,则调用_CrtSetDbgFlag在预处理过程中删除。
因为设置位将导致诊断输出增加、程序执行速度减慢,因此在默认情况下不会设置这些位(已关闭)。
介绍一下函数中用到的一些值
_CRTDBG_REPORT_FLAG
调用_CrtSetDbgFlag与newFlag等于_CRTDBG_REPORT_FLAG以获取当前_crtDbgFlag状态,并在临时变量中存储返回的值。
_CRTDBG_LEAK_CHECK_DF
执行自动泄露检查在程序退出时通过调用 _CrtDumpMemoryLeaks ,则生成错误报告,如果应用程序未能释放其所分配的所有内存。
示例:
#include <string.h>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif // DEBUG
using namespace std;
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
typedef long long ll;
void EnableMemLeakCheck()
{
int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(tmpFlag);
}
class people{
public :
int *a;
people() :a(new int(5))
{
}
};
void test()
{
people *p = new people;
delete p->a;
//delete p; //故意不delete,程序控制台会打印出内存泄漏的位置
}
int main()
{
EnableMemLeakCheck();
test();
system("pause");
return 0;
}
/*
输出:
Detected memory leaks!
Dumping objects ->
f:\vs_workspace\practice\practice\practice.cpp(58) : {146} normal block at 0x000002880770FBF0, 8 bytes long.
Data: <PRp > 50 52 70 07 88 02 00 00
Object dump complete.
*/
#ifdef _DEBUG#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)#endif // DEBUG