捕捉VC程序的内存泄漏

李国帅 2018/2/6

整理以往的调试日志

随着Vc程序规模的不断扩大,内存泄漏问题便成为不得不面对的重要问题,下面总结了几种进行检测的简便方法。像是BoundsChecker这些工具自从v6版本后都变成收费了,虽说挺好用,但是小公司出身的苦哈哈一族就算了。废话不说转入正题。

---------------------

1、使用vld.lib进行检测

对于普通的vc应用程序基本也就够用了,能够检测出基本的内存泄漏,只要不使用特别复杂的内存操作语法。这是一个开源的检测库,可方便的从网上下载。

#ifdef _DEBUG
#include "MemLeakDetect.h"
#endif
/************************************************************************/
/* 调试 */
#ifdef _DEBUG
CMemLeakDetect gMemLeakDetect;
#endif
/************************************************************************/
2、使用vc调试语句

使用vld.lib好像不能对com进行很好的支持,可以简单的使用vc调试语句进行调试,效果也不见得差。使用

#ifdef _DEBUG //只能监视new出来的内存泄漏

#ifndef _CRTDBG_MAP_ALLOC

#define _CRTDBG_MAP_ALLOC //使生成的内存dump包含内存块分配的具体代码为止

#endif

#include <stdlib.h>

#include <crtdbg.h> //for memory leak check

#endif

_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG |_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

_CrtSetBreakAlloc(187);

...

_CrtDumpMemoryLeaks();

出现一些泄露,原因并不是真正的泄露,比如CString变量判断为泄露,实际上不是因为_CrtDumpMemoryLeaks();调用的时候,程序的堆栈还没有真的的退出。

{317} normal block at 0x01C415F8, 496 bytes long.

Data: <) `> 29 00 00 00 04 D9 1B 00 0E 00 00 00 00 00 00 60

{289} normal block at 0x0002EBC8, 2 bytes long.

Data: < > 88 C3

{270} normal block at 0x0002E828, 40 bytes long.

Data: < D > B8 44 8A 01 01 00 00 00 E8 CD 19 00 FF FF FF FF

f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\dllmodul.cpp(133) : {102} client block at 0x00027960, subtype c0, 64 bytes long.

a CDynLinkLibrary object at $00027960, 64 bytes long

{97} client block at 0x00027790, subtype c0, 64 bytes long.

a CDynLinkLibrary object at $00027790, 64 bytes long

f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\oleinit.cpp(84) : {91} client block at 0x00026540, subtype c0, 68 bytes long.

a CCmdTarget object at $00026540, 68 bytes long

f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\plex.cpp(29) : {89} normal block at 0x00026360, 124 bytes long.

Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 D8 1B 02 00

f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\occmgr.cpp(788) : {88} normal block at 0x00021BD8, 4 bytes long.

Data: < : x> DC 3A 1F 78

{65} client block at 0x00021320, subtype c0, 64 bytes long.

a CDynLinkLibrary object at $00021320, 64 bytes long

3、使用umdh查看内存变化

免费的调试工具不多,可以使用vc debug工具集(Debugging Tools for Windows (x86)工具)中使用umdh对比内存是否增长。这个工具相当的方便直接,直接映射运行程序的内存表,然后进行比较。如果进行定位,网上大把的相关教程,不过不用查教程你依然知道内存是否增加了。(windbg可以打印一些信息,不用安装环境。)

输出内存占用,分析vc程序

set _NT_SYMBOL_PATH=d:\mysymbols

gflags -i testplayer.exe +ust

umdh -pn:evclient.exe -f:dump1

umdh -p:2712 -f:dump2

umdh dump1 dump2 -f:Result1.txt

--------------------

4、使用CrashFinder+pdb文件分析崩溃地址
获取PDB文件

要想获取崩溃所在的位置,一定要有调试信息,那么就需要编译程序时生成PDB,map,cod之类的文件,这些文件里包含了进程信息、线程信息、调用堆栈、变量等信息。

如何生成pdb文件( 程序数据库文件)?

配置属性--c/c++ 输出文件-- 汇编输出 = /FAc

--连接器--调试--生成调试信息,生成映射文件,映射导出。

程序发布的时候保存好pdb文件是个好习惯,避免出错也找不到原因。

记录崩溃信息

应用程序在崩溃的时候,会弹出一个框,弹出如下内容:

问题事件名称: APPCRASH

应用程序名: ***.exe

应用程序版本: 1.0.0.2

应用程序时间戳: 51492e42

故障模块名称: ***.ax

故障模块版本: 1.0.0.6

故障模块时间戳: 51492e09

异常代码: c0000005

异常偏移: 0008feb9

使用CrashFinder+pdb文件进行定位

找到偏移位置,故障模块名称: ***.ax和异常偏移: 0008feb9

运行CrashFinder,新建文档输入文件***.ax,ImageBase=0x10000000,所以文件偏移为1008feb9.

输入1008feb9查询Crash,得到

1008FEB9, xxx.AX, CxxxMng::CreateSession, g:\xxx\xxx.cpp line 305

找到新加入的语句:

int *p = NULL;

*p = 100;

只要有pdb文件,定位非常容易。

5、使用崩溃dump文件查找错误的原因。
使用dbghelp.lib或者手动从任务管理器生成dump文件,然后使用vc或者WinDBG打开,也可定位到出错位置,可能效果更好。
如果能把错误信息或者文件一起提交到服务端,那是最好了。
 
关于如何分析dump文件,就不班门弄斧了,最多也就抄一段。

说在最后,查找问题和定位错误有时候并不是那么容易,可能要想很多办法,并不是一个工具一定能够找到问题,也不是使用工具一下就能找到问题,这是一个细致活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微澜-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值