调试Release发布版程序的Crash错误(二)

来源:互联网 发布:轻量级c语言ide 编辑:程序博客网 时间:2024/04/30 08:19

上篇给出的方案一还要补充几句。通过“crash地址 +MAP文件”来定位出错代码位置虽然需要经过比较复杂的地址计算,但却是最简单实现的方式。如果仅仅想通过崩溃地址定位出错的函数,就更加方便了。我在网上找到一个解析MAP文件的小工具,可以非常清晰的列出每个函数的地址,并且可以将分析表格导出为Excel文件。工具下载地址:http://e.ys168.com/?tinyfun,工具目录下VCMapper.exe。

   另外上篇主要参考两篇文章:

    http://www.vckbase.com/document/viewdoc/?id=908

    http://www.vckbase.com/document/viewdoc/?id=1473

 

   方案二:崩溃地址 + MAP文件 +COD文件

   由于VC8以后的版本都不再支持MAP文件中产生代码行信息,因此我们寻找另一种定位方式:COD文件。

   1、COD文件

   COD文件是一个包含了汇编码、二进制机器码和源代码对应信息的文件,每一个cpp都对应一个COD文件。通过这个文件,我们可以非常方便地进行定位。

   在VC6中生成COD文件的设置方式为:Project Settings -> C/C++,在Category 中选 Listing Files,在 Listing file type 组合框中选Assembly,Machine code,and source。在VC8中生成COD文件的设置方式为:ProjectProperties -> C/C++ -> Output Files-> Assembler Output 项,选择 Assembly,Machine code,andSource(/Facs)。

 

   2、定位崩溃行

   下面通过举例进行说明。现在我有一个基于对话框的MFC应用程序CrashTest,在CCrashTestDlg::OnInitDialog函数中写入导致crash的代码语句(第99行),源文件如下:

    调试Release发布版程序的Crash错误(二)

   根据崩溃地址(0x004012A3)以及MAP文件(定位片段图片如下),定位crash函数为OnInitDialog;并且我们可以很容易地计算出崩溃地址相对于崩溃函数的偏移量为0x004012A3 - 0x004011E0 = 0xC3。

    调试Release发布版程序的Crash错误(二)

   再来看看CrashTestDlg.cod文件,我们根据文件中源码信息找到OnInitDialog函数信息片段:

    调试Release发布版程序的Crash错误(二)

   可以看到图片中第一行为OnInitDialog函数汇编代码的起始行;找到“int * p =NULL;”这一句源码,其前面的98表示这行代码在源文件中的行号,下面的000c1表示相对于函数开始位置的偏移量,后面的“33c0”为机器码,“xor eax,eax”为汇编码。那么我们根据前面算出来的偏移量0xC3,找到对应出错的语句为99行:“*p =5;”。

   总结一下定位步骤:

    1) 根据公式崩溃语句在函数中偏移地址 = 崩溃地址 - 崩溃函数地址 计算出偏移量X;

    2) 根据公式崩溃语句在COD文件中地址 = 崩溃函数在COD文件中地址 + X计算出地址Y。其中崩溃函数在COD文件中地址为COD文件中函数起始括号“{”后面表明的地址,一般情况下为0x0000;

    3)根据Y在COD文件中找到对应代码行。

 

   ok,方案二介绍完了。这种方法最大的好处是没有VC开发环境版本限制,而且COD文件里面包含的信息更加丰富,不但可以帮助我们定位crash,还能帮我们分析很多东西。当然,这也导致编译生成了很多信息文件。