基于VS2010 开发的Release版本软件异常崩溃后快速定位bug相关方法

方法:

  • 使用.map以及.cod定位bug(暴力崩溃)
  • 使用.dmp定位bug(优雅崩溃)

注意事项:在最后面^_^。

完整项目源码请点击这里

 

一.使用.map以及.cod定位bug(暴力崩溃)

首先介绍在软件异常崩溃后如何使用.map以及.cod定位bug。

需要进行的工程项目属性配置:

  1. xxx属性->配置属性->C/C++->输出文件->汇编程序输出,选择 程序集、机器码和源代码 (/FAcs)

  

 

  1. xxx属性->配置属性 -> 链接器 -> 调试 -> 生成映射文件,选择 是 (/MAP)

设置好项目属性后,按下F7进行编译,可以看到工程目录下生成对应的.map文件:

那.cod文件在哪里呢?

找不到搜索一下就知道了:

可以看到每个.cpp文件会对应的生成一个.cod。

下面来演示一下如何使用.map以及.cod精确定位到程序崩溃的位置:

首先,运行.exe,让它暴力的崩掉:

这是一件很恐怖的事情!

接下来,我们点击一下“查看问题详细信息”这个扩展按钮;

凉凉!差点。还好这次我们还有神器.map和.cod。

下面就是见证奇迹的地方:

a1. 打开.map文件(vs就可以打开了,当然用记事本也是没有问题滴),我们可以看到开头的是这几行:

ExceptionHandleTest:工程名

Timestamp is 5c7de239 (Tue Mar 05 10:43:05 2019):工程是什么时间编译的

Preferred load address is 0000000140000000:(三角形重点)基地址

接下来是data段了,这里不用管。

再继续往下看,可以看到画红色底线这行了,重点又来了:

Rva:偏移地址

Base:基地址

红色线下面开始就是函数信息,而我们需要的信息隐藏在其中。

在Windows弹出的崩溃信息窗口可以看到

偏移地址:0000000000001ce5

而基地址(在.map开头):0000000140000000

那么软件崩溃的Rva+Base就是0000000140001ce5这里了,当然.map里并没有对每一个地址都做详尽的记录,我们要做的是找到比这个地址小一点的地方就能大概找到崩溃的位置了。

在本例中,Ctrl+F,输入0140001c进行查找

刚好找到一个比0000000140001ce5稍微要小的地址,我们来看一下这一行告诉了我们什么信息

可以看到,这这里是ExceptionHandleTestDlg的fun函数里,对应地址是0000000140001c90。到了这里可以大概定位到了崩溃函数的位置了。但是我们还可以更进一步定位到是在哪一行代码崩溃的。

终于轮到我们的.cod出场了。

找到ExceptionHandleTestDlg.cod,双击打开,查找到以?fun@CExceptionHandleTestDlg开头的一行

包含这一串字符的会有不少行,但是以其开头的只有这一行,对,就是蓝色这一行。

然后我们来看一看我们找到的这一行下面的是什么

; 179  : int b[10];   --> 行数 : 源码

0001d c7 44 24 60 00   --> 偏移地址   机器码

 

接下来我们就要做一个简单的计算,以确定是在哪一行崩了的。

从windows弹出的软件崩溃提示信息窗口中我们得知的:

异常偏移地址Rva:0000000000001ce5

那么异常地址 expeAddr = expeRva + Base = 0000000140001ce5

而我们找到的函数地址 findAddr = 0000000140001c90

那么导致崩溃对应的代码所在行的偏移地址 = expeAddr - findAddr = 0x0055

那么我们找到fun函数下偏移0055的地方:

从这行往上一点点,我们看到了: ; 193  : *c = 5;  

好开心,终于找到你了。

然后打开CExceptionHandleTestDlg.cpp,找到第193行,可以看到:

我的天,竟然定义了指针,没开辟内存就直接赋值了。

至此,利用.map和.cod两大神器找崩结束,修bug就交给你了。

 

 

 

二.使用.dmp定位bug(优雅崩溃)

首先需要进行的工程项目属性配置:

1.xxx属性 -> 配置属性 -> C/C++ -> 常规 -> 调试信息格式,选择 程序数据库 (/Zi)

  1. xxx属性 -> 配置属性 -> C/C++ -> 优化 -> 优化,选择 已禁用 (/Od)

(浅尝不选这个也行,尚未深究)

  1. xxx属性 -> 配置属性 -> 连接器 -> 调试 -> 生成调试信息,选择

接下来就是如何生成.bmp文件了,详情观看一下例程。

CExceptionHandleTestApp.h类中#include "HiExceptionHandle.h",并定义一个HiExceptionHandle类对象excep:

然后在启动软件时,运行的比较早的函数中添加函数调用:excep.RunCrashHandler();

然后,F7编译。

接着再次让软件进入崩溃:

可以看到这次显示竟然不是Windows自动弹出的“xxx停止工作”那个让人绝望的窗口了,而是弹出我们自己设定的窗口,点击确定就可以优雅的关掉软件了,并且可以看到关掉软件后生成了.dmp文件:

 

下面就让我们来试一下如何.dmp来快速定位使软件崩溃的位置吧。

双击打开HiMiniDump.dmp(VS2010即可打开),进入以下界面:

在该界面中,我们可以看到并不明显的右上角“操作”这个框框:

那么在此呢,我们需要保证几个东西的一致性,即.exe .pdb .dmp是同一个版本的,当然还有相对应的源码也要保持一致。

然后接下来呢,有两种情况:

  1. .dmp文件是跟我们工程是放在一起的,那么直接点击“使用 仅限本机 进行调试”,即可定位到使程序发生崩溃的地方啦啦啦。
  2. 我们.exe是发布出去的,是在另一台电脑上使用的,或者随便找个文件夹丢进去测试的,当我们用VS2010打开.dmp文件,需要点击“设置符号路径”进行简单的设置。例如我在“D:\\新建文件夹\\Release”进行测试,

那么设置一下符号路径:

(其实我在本机上也不用这么设置,但是拷贝到另一台电脑测试时就要)

点击“确定”,然后点击“使用 仅限本机 进行调试”,进入以下界面:

点击“中断”,这里需要稍等一会儿,莫心急哈。

然后,我们把“调用堆栈”的滑条滑到最上面,你就能惊奇的发现点蛛丝马迹:

对!就是这个:

> ExceptionHandleTest.exe!CExceptionHandleTestDlg::fun(int * a)  行 193 + 0x5 字节 C++

然后兴奋的双击它,额!怎么弹出下面这个框的?

嗦嘎,原来是需要对应的源文件,那就找到这个.cpp,拷过来瞧一瞧会发生点什么吧。

把对应的.cpp放进去后,打开,竟然,竟然神奇的定位到了念念不忘的可爱的bug的位置了:

至此,完成了使软件崩溃的bug的查找,完善bug就交给你了。

注意事项

以上两种方法的使用都有前提,那就是要保证用到的文件要保持版本一致性,所以要做好相应的备份哦!

另外,在测试中发现数组越界导致的崩溃竟无法定位到,好伤心,各位大神大咖有什么建议意见还望不吝指点小弟迷津。感激阅读!

完整工程源码请点击这里

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值