Windows平台下如何检测C/C++内存泄露?

作者: NickYang 分类: 技术文章,程序开发 发布时间: 2012-10-14 19:02

如何检测内存泄露

对于C/C++程序员来说,效率和优雅性大多数情况是对立的,我们经常会在这里面抉择,到底应该怎么取舍。而说到效率,就不得不说让这类程序员头疼了N年的问题,内存泄露,至少从C/C++发明以来很多人都在头疼。而Java/C#之类的语言并不存在这种问题,因为他们从堆中申请内存,根据引用计数等(据说有六种方法,大家可以搜一下Java垃圾回收器简介)方法来管理内存,也就是传说中的垃圾回收器(Garbage collector)。C/C++的程序员一向都是相信自己对内存的掌控能力,所以经常会出现各种内存泄露问题,有可能是因为自己疏忽大意,有可能是因为坑太深了,有可能是潜规则,总之,我们要做的是解决问题。

1.使用Window说自身的宏_CrtDumpMemoryLeaks

例如我们有如下的代码:

执行之后,在输出窗口中会打印如下内容:

Detected memory leaks!
Dumping objects ->
{108} normal block at 0x003BA1C0, 40 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
程序“[5364] AllTest.exe”已退出,返回值为 0 (0x0)。

他会告诉你检测到内存泄露,泄露了多少字节等内容。

遗憾的是看不到那里内存泄露了,我们可以稍微改下这个代码,让他支持在哪个文件的哪个函数里哪一行有内存泄露。修改内容如下:

再次运行输出窗口的内容如下:

Detected memory leaks!
Dumping objects ->
d:\project\alltest\alltest\alltest.cpp(12) : {108} normal block at 0x0060A1C0, 40 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
程序“[6372] AllTest.exe”已退出,返回值为 0 (0x0)。

它标明了alltest.cpp第12行有内存泄露,泄露内存块在0x0060A1C0位置,泄露大小为40字节,这样就能帮助我们快速的定位问题所在了。

 

2.Visual Leak Detector 库(VLD)

项目主页地址:http://vld.codeplex.com/,codeproject和sourceforge上都有其项目主页,大家可以自行选择下载。

其中包含Windows版本和源代码版本,windows版本是头文件和lib文件,用户可以自行调用,而源码版本可以自己编译。

使用方法异常简单,只需要包含vld.h头文件即可

———- Block 58 at 0x004EBF58: 76 bytes ———-
  Call Stack:
    d:\project\alltest\alltest\alltest.cpp (9): AllTest.exe!wmain + 0x7 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (240): AllTest.exe!__tmainCRTStartup + 0x19 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (164): AllTest.exe!wmainCRTStartup
    0x75C8339A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
    0x772C9EF2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
    0x772C9EC5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
  Data:
    40 BA 4E 00    00 00 00 00    00 00 00 00    00 00 00 00     @.N….. ……..
    28 00 00 00    01 00 00 00    3A 00 00 00    FD FD FD FD     (……. :…….
    CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     …….. ……..
    CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     …….. ……..
    CD CD CD CD    CD CD CD CD    FD FD FD FD                    …….. ……..

Visual Leak Detector detected 50 memory leaks (6904 bytes).
Largest number used: 11346 bytes.
Total allocations: 17030 bytes.
Visual Leak Detector is now exiting.

通过上面蓝色加粗的字体我们就很容易得知具体的泄露位置了。而且VLD现在2.2.3的新版本有一个vld.ini文件,用来配置各种开关和参数,具体的配置说明请查看http://vld.codeplex.com/wikipage?title=Configuration%20Options&referringTitle=Documentation

注意:如果你发现你按照这种做法做了,但是却出现0xc0150002的问题,请拷贝vld安装目录下的对应平台的Microsoft.DTfW.DHL.manifest和dbghelp.dll到你的程序目录下。(To ensure that vld.dll finds the required private assembly, you need to copy dbghelp.dll and Microsoft.DTfW.DHL.manifest to the same directory that vld.dll is in.)

最后不得不吐槽一下这种需要lib还需要dll的方法,甚至还需要对应mainfest文件,太麻烦了,还不如直接给一个Lib完事了。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

5条评论
  • egmkang

    2012 年 11 月 4 日 22:37

    在linux下就ez多了,程序搞完了,用valgrind跑一下就可以了,比如a.out
    valgrind –tool=memcheck ./a.out
    坐等输出吧

    吐槽 其它浏览器 其它操作系统
  • eliteYang

    2012 年 10 月 26 日 22:36

    测试

    神话 其它浏览器 其它操作系统
  • rangerlee

    2012 年 10 月 17 日 23:26

    我常用的是vld,不过这些都只是些参考,分析过程还是很痛苦的!

    畅言 其它浏览器 其它操作系统
    1. eliteYang

      2012 年 10 月 18 日 15:48

      还可以用bounder check,这个就是分析起来太卡了

      神话 其它浏览器 其它操作系统
  • 我的名字叫麒

    2012 年 10 月 17 日 20:32

    最近在自学windows sdk,希望能在博主这里学习!

    潜水 其它浏览器 其它操作系统

发表评论

电子邮件地址不会被公开。 必填项已用*标注