如何定位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等工具进行检测。
下面是在总结的一些方法,均来自网上,也经历了实际检验,在此备份。
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等工具进行检测。
相关文章推荐
- C++内存泄露问题定位经验案例
- C++中如何避免内存泄露
- 如何查看C++内存泄露
- 定位C++内存泄露位置
- 如何检查内存泄露并进行定位
- C++技术问题总结-第15篇 内存泄露有哪些方法定位,崩溃有哪些方法定位
- 如何使用Valgrind内存检查工具 检查C/C++中内存泄露
- c/c++如何查看处理内存泄露
- Wince内存泄露检测工具Application Verifier的使用和如何快速定位泄露语句(二)
- C/C++内存泄露--工程中如何尽量避免
- C/C++ 内存泄露检测 Visual Leak Detector 检测定位内存泄露 对malloc和new均适用
- Wince内存泄露检测工具Application Verifier的使用和如何快速定位泄露语句
- Dojo-最佳实践如何防止浏览器内存泄露
- C++内存管理之一(检测内存泄露)
- C++内存管理之一(检测内存泄露)
- 最近在SPARK上定位的几个内存泄露问题总结
- 在iPhone应用中如何避免内存泄露
- 使用Visual Leak Detector for Visual C++ 捕捉内存泄露---Visual C++内存泄露检测—VLD工具使用说明
- Android中如何查找内存泄露
- c++内存泄露之重载new运算符