前言
之前在面一家公司的时候被问及到:当你接收同事的项目,项目之中可能存在内存泄露,而且代码能够正常的运行不会报错。在这种情况下找出该项目中可能存在的内存泄露问题(比如原同事只new了但是没有delete),该如何进行检测。这样的问题确实很实用,因为在软件编写的过程中不仅仅需要完成软件功能,更加重要的是代码的健壮性。
至于Linux平台下的内存泄露检测在这篇博客里面进行了介绍。
1. Win32平台下
对于堆上内存操作(new,malloc)的检测,可以使用在Win32平台使用_CrtDumpMemoryLeaks()函数对内存泄露进行检测,实现的代码如下
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
int _tmain(int argc, _TCHAR* argv[])
{
system("color f0");
int *p_array = new int[10];
_CrtDumpMemoryLeaks(); //检测内存泄露
system("pause");
return 0;
}
输出结果:
注意:_CrtDumpMemoryLeaks()函数在上面代码的使用中需要写在函数的末尾,这样才能够检测到。
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
#define My_new new(_NORMAL_BLOCK, __FILE__, __LINE__) //定义一个自定义的new
int _tmain(int argc, _TCHAR* argv[])
{
system("color f0");
int *p_array = My_new int[10];
_CrtDumpMemoryLeaks(); //检测内存泄露
system("pause");
return 0;
}
输出结果:
如果想要不将_CrtDumpMemoryLeaks()函数放在尾部,就需要提前做好配置,代码为(参考资料(中文))
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
#define My_new new(_NORMAL_BLOCK, __FILE__, __LINE__) //定义一个自定义的new
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF);
system("color f0");
int *p_array = My_new int[10];
system("pause");
return 0;
}
输出结果:
_CrtDumpMemoryLeaks一般都在有怀疑是内存泄漏的代码后面调用,除了这个函数之外使用率会比较高的函数是_CrtMemCheckpoint, 设置一个内存检查点。这个函数会取得当前内存的运行状态;_CrtMemDifference,检查两种内存状态的异同; _CrtMemDumpAllObjectsSince,从程序运行开始,或者从某个内存检查点开始Dump出堆中对象的信息;还有就是_CrtDumpMemoryLeaks当发生内存溢出的时候Dump出堆中的内存信息 。
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
#include <errno.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
#define My_new new(_NORMAL_BLOCK, __FILE__, __LINE__) //定义一个自定义的new
int _tmain(int argc, _TCHAR* argv[])
{
system("color f0");
_CrtMemState Sh1, Sh2, Sh_Diff;
int* p_array1 = My_new int[10];
_CrtMemCheckpoint(&Sh1); //设置第一个内存检查点
int* p_array2 = My_new int[10];
memset(p_array2, 0, sizeof(int)*10);
_CrtMemCheckpoint(&Sh2); //设置第二个内存检查点
_CrtMemDifference(&Sh_Diff, &Sh1, &Sh2); //检查变化
_CrtMemDumpAllObjectsSince(&Sh_Diff); //Dump变化
system("pause");
return 0;
}
输出结果:
2. MFC环境平台下
Debug版本的MFC本身就提供一部分的内存泄漏检查。 大部分的new 和delete没有配对使用而产生的内存泄漏,MFC都会产生报告。这个主要是因为MFC重载了Debug版本的new 和delete操作符, 并且对前面提到的API函数重新进行了包装。在MFC类库中检查内存泄漏的Class就叫 CMemoryState,它重新包装了了_CrtMemState,_CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince这些函数。并对于其他的函数提供了Afx开头的函数,供MFC程序使用。比如 AfxCheckMemory, AfxDumpMemoryLeaks 这些函数的基本用法同上面提到的差不多。 CMemoryState和相关的函数的定义都在Afx.h这个头文件中。
一般在*.cpp文件中会出现下面几行代码
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
这是对DEBUG_NEW的定义
#define DEBUG_NEW new(THIS_FILE, __LINE__)
相当于MFC已经包装好了,只需要使用就好了。下面是我写的一个测试用例
void CFile_TransDlg::OnBnClickedButtonTest()
{
// TODO: 在此添加控件通知处理程序代码
int* p_array = new int[10];
AfxDumpMemoryLeaks();
}
输出结果:
本文介绍了在Windows环境下,如何检测C++程序中的内存泄露问题。针对Win32平台和MFC环境,分别提供了利用_CrtDumpMemoryLeaks()函数和MFC自带的内存泄漏检查方法。在Win32下,可以通过设置内存检查点和使用_CrtMemDifference等函数来跟踪内存状态。而在MFC环境中,MFC重载了new和delete,并提供了CMemoryState类及相关函数进行内存泄漏检测。
1452

被折叠的 条评论
为什么被折叠?



