您的位置:首页 > 编程语言 > C语言/C++

如何定位c++内存泄露

2013-01-07 11:10 951 查看
在进行C++开发时,如果在windows平台上,使用MFC,则可以自动检测内存泄露,如果是win32或者console程序,不使用MFC,则需要自己进行处理。

下面是在总结的一些方法,均来自网上,也经历了实际检验,在此备份。

1. 利用 KDetectMemoryLeak.h来完成类似MFC重定义NEW宏的效果。可以完成泄露点的输出。

在代码的最后,采用_CrtDumpMemoryLeaks();

具体可以参见《VS2008内存泄露检测》文档,作者写的很清楚,在此谢谢。

KDetectMemoryLeak.h 源码:

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

2. 对于无法定位到具体源代码的泄露,可以通过分析dump出来的信息来定位。

特别是在DLL库中,经常会出现这种情况。

比如:

{152} normal block at 0x01078320, 12 bytes long.

Data: 08 79 65 00 48 82 07 01 00 00 00 00

{151} normal block at 0x010782C0, 36 bytes long.

Data: CD CD CD CD CD CD CD CD 00 00 00 00 00 00 0000

{150} normal block at 0x01078248, 56 bytes long.

Data: F4 77 65 00 00 00 00 00 68 71 07 01 90 3A 0910

《软件调试》的702页介绍了堆块转储的细节,取其中的一个堆块为例:

{137} normal block at 0x01073790, 8 bytes long.

Data: <H7> 48 37 07 01 CD CD CD CD

137是堆块的分配序号,堆块的类型为普通堆块,位置为0x01073790,用户区长度为8字节。

Data后为用户数据区的前16字节,因为这个数据区只有8字节,所以即所有8字节。<H7>是这8字节的ASCII码显示(其它6字节为不可显示的ASCII码)。其中的CD CD CDCD 是CRT在分配堆块时自动填充的固定内容(《软件调试》P696)。这说明这8个字节的堆块,应用程序使用过前4个字节,后四个字节没有使用过。

对于这样的内存泄漏,有很多种办法,你首先可以试一下23.13.1节介绍的内存分配序号断点,也就是重新运行程序,在尽可能早的时候(比如入口),设置序号断点(将_crtBreakAlloc变量设置为要中断的序号,比如137),让CRT分配到指定的内存块时中断。中断下来后,可以根据栈回溯判断是哪个模块在分配内存,记录后,再退出程序,如果这个堆块仍出现在转储列表中,那么刚才那个模块便值得怀疑了。

如果你有被怀疑的模块源代码,那么可以使用23.15.3节介绍的方法让堆块转储信息中包含源程序的文件名和行号,即下面的样子:

C:\dig\dbg\author\code\chap23\MemLeak\MemLeak.cpp(22): {74} normal block at 0x00371000, 20 bytes long.

Data: CD CD CD CD CD CD CD CD CD CD CD CD CD CD CDCD

3.可以利用 vld 进行检测。

4.还可以利用 boundcheck,purify等工具进行检测。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: