有关内存泄露检测的一些知识。

来源:互联网 发布:mac 命令行 修复系统 编辑:程序博客网 时间:2024/05/18 03:24

在练习智能指针代码实现双链表的时候,由于担心引发循环引用,导致内存泄露,所以在测试的文件中加入了检测内存泄露的一些语句。作为了解,在这里也简单的说一下有关内存泄露检测的一些方法。其中参考了msdn的一些内容

首先说明,如果想要启用内存泄露检测,需要包含头文件:crtdbg.h

如果只是想简单的了解到底内存是否泄露,可以在包含了头文件crtdbg.h文件之后。在程序即将结束退出之前加入下面的函数:

_CrtDumpMemoryLeaks();

那么在调试器状态下,如果发生了内存的泄露,在输出(调试信息)栏里面就会出现:

Detected memory leaks!Dumping objects ->{18}normal block at 0x0070FFE0, 64 bytes long. Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CDObject dump complete.

如果程序存在多个出口,我们当然不必在每个出口都加上_CrtDumpMemoryLeaks()。根据msdn中描述的如下:检测内存泄漏的主要工具是调试器和 C 运行时库 (CRT) 调试堆函数。若要启用调试堆函数,请在程序中包括以下语句:

#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>
#include 语句必须采用上文所示顺序。如果更改了顺序,所使用的函数可能无法正确工作。通过包括 crtdbg.h,将 malloc 和 free 函数映射到其“Debug”版本 _malloc_dbg 和 _free_dbg,这些函数将跟踪内存分配和释放。


当然我们写程序到达这里肯定是不甘心的,如果我们的代码中出现了内存泄露,我们当然想要知道问题到底出现在哪里。

我在网上查了不少的资料,其中在刚刚的MSDN中介绍,如果要显示这样的效果:

Detected memory leaks!Dumping objects ->c:\projects\test.cpp(26) : {137} normal block at 0x00848A28, 4 bytes long. Data: <    > 06 00 00 00 Object dump complete.

msdn上介绍说,需要在程序的开始加上下面的语句:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

但是经过测试发现这不能实现,可能是老版本的实现吧。

后来google了一下发现了新的方法,但是看上去好像有些繁琐。贴上我的测试的文件:

#ifdef _DEBUG#define MYDEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)// Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the//allocations to be of _CLIENT_BLOCK type#else#define MYDEBUG_NEW#endif // _DEBUG
#ifdef _DEBUG#define new MYDEBUG_NEW#endif
#include <iostream>#include <crtdbg.h>
int main(){{int* a = new int(6);}_CrtDumpMemoryLeaks();return 0;}

在程序的最上头,加上这么一些宏定义就可以实现如下效果:

Detected memory leaks!Dumping objects ->c:\users\jmy\documents\visual studio 2012\projects\test\test.cpp(19) : {137} normal block at 0x00858858, 4 bytes long. Data: <    > 06 00 00 00 Object dump complete.

显示出了代码所在的文件,和代码所在文件的行数。

还有另外的一种形式,设置程序的断点,_CrtSetBreakAlloc(long number);其中的number就是上面在程序泄露的时候,分配内存的次数,即第几次分配内存。

如,上图中的{137}就是应该的number值。 

#include <crtdbg.h>inline void EnableMemLeakCheck(){_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);}int main(){EnableMemLeakCheck();_CrtSetBreakAlloc(137);int* a = new int(8);_CrtDumpMemoryLeaks();return 0;}

通过上面的调用,当程序执行到哪个内存分配的时候,断点就会停在那里。也可以起到找到问题代码所在行的目的。

暂时先更新到这里,有问题大家再提。




原创粉丝点击