C++ 内存泄漏检测方法

版权声明:本文为博主原创文章,如需转载请注明出处 https://blog.csdn.net/bajianxiaofendui/article/details/83414328


     程序中通常包含着静态存储区和栈内存。静态存储区也就是静态内存,是用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量(全局变量)。栈内存用来保存定义在函数内的非static对象。分配在静态或栈内存中的对象由编译器自动创建和销毁。对于栈对象,仅在定义的程序块运行时才存在,程序退出,栈对象也随之销毁;static对象和全局对象则是在程序结束时销毁。除了静态内存和栈内存,程序还拥有一块内存池,这部分也就是称为堆。在使用堆空间是就需要使用动态内存分配。
内存泄漏:是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
对于c++而言,造成内存泄漏的就是new和malloc,通过new申请的堆内存没有使用delete来释放,通过malloc分配的堆内存没有使用free来释放。

一,MFC宏定义

     大家使用visual studio编译器或者VC6.0创建MFC程序的时候,在默认生成的类的cpp文件上方,可以看到使用#ifndef…#define…#endif来定义了一些宏,而这些宏中恰恰就有涉及到内存操作的操作符new。

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

     当在debug模式下时,我们分配内存时的new被替换成DEBUG_NEW,而这个DEBUG_NEW不仅要传入内存块的大小,还要传入源文件名和行号。在程序退出时,如果发生内存泄漏,我们可以在编译器的输出界面清楚地看到发生内存泄漏的代码文件以及行号,以便于我们直接定位问题。
在这里插入图片描述
     在stackoverflow上查找了这种实现方式的原理,也没有答案,但是结合下文要说的第二种方式,我推断MFC应该是自己内部封装实现了_CrtDumpMemoryLeaks()。

二,_CrtDumpMemoryLeaks

     C运行库的Debug版本提供了许多检测功能,使得我们更容易的Debug程序,我们会用到里面很重要的几个函数。其中最重要的是 _CrtDumpMemoryLeaks();自己看MSDN里的帮助吧。使用这个函数,需要包含头文件crtdbg.h
     该函数只在Debug版本才有用,当在调试器下运行程序时,_CrtDumpMemoryLeaks 将在“Output(输出)”窗口中显示内存泄漏信息。但是这个函数只能输出是否有内存泄漏,并不能定位到哪里出现了内存泄漏,因此我们需要参考mfc的方式来加入文件名称和代码行号。

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

     在我们程序退出前的最后一个地方调用_CrtDumpMemoryLeaks ()即可,例子如下:

int _tmain(int argc, _TCHAR* argv[])
{
	int* p = new int();

	char* c = new char;

	_CrtDumpMemoryLeaks();
	return 0;
}

     编译器输出界面如下:
在这里插入图片描述
     双击泄漏的地方即可直接定位代码处进行修改。

三,VLD

     Visual LeakDetector(VLD)是一款用于Visual C++的免费的内存泄露检测工具。它的特点有:(1)、它是免费开源的,采用LGPL协议;(2)、它可以得到内存泄露点的调用堆栈,可以获取到所在文件及行号;(3)、它可以得到泄露内存的完整数据;(4)、它可以设置内存泄露报告的级别。
VLD的源码可以从https://archive.codeplex.com/?p=vld上下载,找到vld\sourceCode\vld\vld_vs14.sln可以使用vs2015打开.
1,编译vld工程,在src/bin/Win32/Debug-v140下生成了vld.lib和vld_x86.dll和dbghelp.dll。
2,把vld.lib放到工程代码同目录下,把vld_x86.dll和dbghelp.dll放到exe目录下(或dll目录下),同时加上Microsoft.DTfW.DHL.manifest文件。
3,把vld.h和vld_def.h这两个头文件加入到工程项目中,在整个程序中都会包含的头文件里加入#include “vld.h”(比如含有预编译头的工程,则直接加到stdafx.h中)。
vld默认只在debug模式下检测内存泄漏,所以我们需要以debug运行程序,测试程序如下:
在这里插入图片描述
     程序运行结束后,在vs下方的输出界面会有如下输出信息:
在这里插入图片描述
     可以统计出程序中发生内存泄漏的数目,和泄漏的字节数,并且可以精准定位到代码位置。

四,CppCheck

     CppCheck是一款c++代码检测工具,可以检测代码使用规范,以及内存泄漏问题,它是一款单独的应用程序,打开之后,直接选择c++工程,即可开始检测,检测效果如下:
在这里插入图片描述
     附上CppCheck(64位)下载链接CppCheck下载

猜你喜欢

转载自blog.csdn.net/bajianxiaofendui/article/details/83414328