MS-VC 使用MAP文件快速定位程序崩溃代码行

Qt项目生成map和pdb文件 默认情况下,Qt项目在window系统发布版本不生成map/pdb文件。 将以下内容添加到.pro文件中: QMAKE_LFLAGS_RELEASE+=/MAP QMAKE_CFLAGS_RELEASE += /Zi QMAKE_LFLAGS_RELEASE +=/debug /opt:ref 阅读详情
作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕,反而是测试的成功。我们更为关心的是程序中的哪一行导致了系统崩溃,这样我们才能有针对性的进行改正。
  在VC中,我们可以利用出现程序崩溃时VC的自动跳转,定位到出错代码行。但在大量的压力测试时,尤其是多线程测试时,同时出现几十个错,这时VC本身的出错跳转往往会失灵。
  在这里我们介绍一种辅助查找程序崩溃代码行的好方法,它的核心就是利用编译时生成MAP文件中的信息来定位代码行。
下面就开始我们的介绍。
  首先我们必须生成程序的MAP文件。那么什么是 MAP 文件呢?简单地讲, MAP 文件是程序的全局符号、源文件和代码行号信息的唯一的文本表示方法,是整个程序工程信息的静态文本。它可以在任何地方、任何时候使用,不需要有额外的程序进行支持,仅仅通过一个文本阅读工具如Ultra Edit就可以打开了。而且,这是唯一能找出程序崩溃代码行的救星。
  那么我们应该如何生成MAP文件呢?在 VC 中,我们可以按下 Alt+F7,打开“Project Settings”选项页,选择 C/C++ 选项卡,并在最下面的 Project Options 里面输入:/Zd ,然后要选择 Link 选项卡,选中“Generate mapfile”复选框,并在最下面的 Project Options 里面输入:/mapinfo:lines,表示生成 MAP 文件时,加入行信息。最后按下 F7 来编译生成 EXE 可执行文件和 MAP 文件,此时可以在工程的Debug目录下找到刚刚生成的MAP文件,文件名为“工程名.map”。
  通过上面的步骤,已经得到了 MAP 文件,那么我们该如何利用它呢?让我们从一个简单的实例入手,一步一步演示使用MAP文件定位程序崩溃行的过程。
首先假设我们的VC工程中有下面这个文件:
//*****************************************************
// 程序名称:演示如何通过崩溃地址找出源代码的出错行
// 作者:刘可
// 日期:2003-6-19
// 本程序会产生“除0错误”,所以会导致
// 程序崩溃,弹出“非法操作”对话框。
//******************************************************
#include

int crashtest(int a,int b)
{
int c;
c = a/b;
return c;
}

void main(void)
{
int a = 30;
int b = 0;
int ret;
printf("let's begin crash test.../n");
ret = crashtest(a,b);
}

很显然本程序有“除0错误”,在 Debug 方式下编译,运行时会产生“非法操作”。我们记录下产生崩溃的地址——在我的机器上是 0x0040102f 。这个在不同的机器上可能地址不同,但记下这个地址我们下面将要使用。
我们打开它的 MAP 文件:(这里列出我们比较关心的内容,其他的就略过了)

abort(工程名)

Timestamp is 3ef16533 (Thu Jun 19 15:24:35 2003)

Preferred load address is 00400000

Start    Length    Name        Class
0001:00000000 0001081dH .text        CODE
0002:00000000 000013baH .rdata        DATA
0002:000013ba 00000000H .edata        DATA
0003:00000000 00000104H .CRT$XCA       DATA
0003:00000104 00000104H .CRT$XCZ       DATA
0003:00000208 00000104H .CRT$XIA       DATA
0003:0000030c 00000109H .CRT$XIC       DATA
0003:00000418 00000104H .CRT$XIZ       DATA
0003:0000051c 00000104H .CRT$XPA       DATA
0003:00000620 00000104H .CRT$XPX       DATA
0003:00000724 00000104H .CRT$XPZ       DATA
0003:00000828  00000104H .CRT$XTA       DATA
0003:0000092c  00000104H .CRT$XTZ       DATA
0003:00000a30  00003236H .data        DATA
0003:00003c68  000019c8H .bss        DATA
0004:00000000  00000014H .idata$2       DATA
0004:00000014  00000014H .idata$3       DATA
0004:00000028  00000120H .idata$       DATA
0004:00000148  00000120H .idata$5        DATA
0004:00000268  000004f4H .idata$6       DATA

Address Publics by Value Rva+Base Lib:Object

0001:00000020 ?crashtest@@YAHHH@Z 00401020 f main.obj
0001:0000003c _main 0040103c f main.obj
0001:000000b0 _printf 004010b0 f LIBCD:printf.obj
0001:00000130 __chkesp 00401130 f LIBCD:chkesp.obj
0001:00000170 _mainCRTStartup 00401170 f LIBCD:crt0.obj
0001:000002a0 __amsg_exit 004012a0 f LIBCD:crt0.obj
0001:00000300 __stbuf 00401300 f LIBCD:_sftbuf.obj
0001:00000460 __ftbuf 00401460 f LIBCD:_sftbuf.obj
0001:00000520 __output 00401520 f LIBCD:output.obj
0001:000013c0 ___initstdio 004023c0 f LIBCD:_file.obj
0001:000014f0 ___endstdio 004024f0 f LIBCD:_file.obj
0001:00001510 __CrtDbgBreak 00402510 f LIBCD:dbgrpt.obj
0001:00001520 __CrtSetReportMode 00402520 f LIBCD:dbgrpt.obj
0001:00001580 __CrtSetReportFile 00402580 f LIBCD:dbgrpt.obj
0001:00001600 __CrtSetReportHook 00402600 f LIBCD:dbgrpt.obj
0001:00001620 __CrtDbgReport 00402620 f LIBCD:dbgrpt.obj

  如果仔细浏览 Rva+Base 这栏,我们可以发现第一个比崩溃地址 0x0040102f 大的函数地址是 0x0040103c ,所以在 0x0040103c 这个地址之前的那个入口就是产生崩溃的函数,也就是这行:

0001:00000020 ?crashtest@@YAHHH@Z 00401020 f main.obj

  因此,发生崩溃的函数就是 ?crashtest@@YAHHH@Z,所有以问号开头的函数名称都是 C++ 修饰的名称。所以在我们的源程序中,这个发生崩溃的函数就是 crashtest ()!

  现在我们便轻而易举地知道了发生崩溃的函数名称。把它记下来,然后我们将要直接定位发生崩溃的代码行了。我们注意 MAP 文件的最后部分——代码行信息(Line numbers information),它是以这样的形式显示的:

Line numbers for ./Debug/main.obj(D:/我的工作/技术/出异常例子abort/main.cpp) segment .text

12 0001:00000020 14 0001:0000002b 15 0001:00000035 16 0001:00000038
19 0001:0000003c 20 0001:00000057 21 0001:0000005e 23 0001:00000065
24 0001:00000072 25 0001:00000085

  第一个数字代表在源代码中的代码行号,第二个数是该代码行在所属的代码段中的偏移量。如果要查找代码行号,需要使用下面的公式做一些十六进制的减法运算:

崩溃行偏移 = 崩溃地址(Crash Address)- 基地址(ImageBase Address)- 0x1000

  为什么要这样做呢?因为我们得到的崩溃地址都是由 偏移地址(Rva)+ 基地址(Base)得来的,所以在计算行号的时候要把基地址减去。一般情况下,基地址的值是 0x00400000 。另外,由于一般的 PE 文件的代码段都是从 0x1000 偏移开始的,所以也必须减去 0x1000 。
  所以我们的:崩溃行偏移 = 0x0040102f - 0x00400000 - 0x1000 = 0x2f
我们在MAP 文件的中的代码行信息里查找不超过计算结果0x2f,但却最接近的数。发现是 main.cpp 文件中的:

14 0001:0000002b

  也就意味着在源代码中的第 14 行!让我们来看看源代码,注意注释行和空行也要计算在内,程序的第14行为:

c = a/b;

果然就是第 14 行啊,它发生了“除0异常”!

  方法已经介绍完了,从今以后,我们就可以精确地定位到源代码中的崩溃行,而且只要编译器可以生成 MAP 文件,无论在WIN平台还是UNIX平台,本方法都是适用的。
  本文我们只是列举了一个非常简单的“除0异常”例子,使用MAP文件的效力或许还不十分明显。但相信在我们的大型应用系统调试中,使用MAP文件的辅助方法来快速定位发生程序崩溃的函数以及代码行,将会为我们的程序调试工作节省大量时间和精力,提高我们的调试质量。我们甚至可以要求远地用户直接提供程序崩溃的地址,然后就可以在自己机器上利用MAP文件静态地找到出错的那行,并在程序中进行相应修正了。
 
qt实现软件崩溃定位错误 立即下载

相关推荐

MS-VC-使用MAP文件快速定位程序崩溃代码行-VC++

作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕,反而是测试的成功。我们更为关心的是程序中的哪一行导致了系统崩溃,这样我们才能有针对性的进行改正。

使用MAP文件快速定位程序崩溃代码行

引用地址:http://www.tongtech.com/jsqy/yqxwview.asp?id=105TongSEC组 刘可  作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕,反而是测试的成功。我们更为关心的是程序中的哪一行导致

winki7的专栏 1863

深入CARLA地图底层:OpenDRIVE文件如何影响你的仿真效果与避坑指南

本文深入解析CARLA仿真中OpenDRIVE地图文件的核心作用,揭示其如何影响车道连接、交通规则和导航逻辑。通过实战案例和代码示例,提供五大典型地图问题的诊断与修复方案,帮助开发者优化仿真效果并规避常见陷阱。

weixin_34180452的博客 278

STL中map的[]运算导致程序挂掉的问题

在项目的开发中,使用[]设置map变量时,出现了Segment Fault的问题,使用GDB bt命令得到调用栈(中间部分被我去掉了)如下: #0 0x00000000008da74a in std::local_Rb_tree_decrement(std::_Rb_tree_node_base*) () Missing separate debuginfos, use: debuginfo...

u014209688的专栏 4631

手把手教你用TJA1145A实现CAN节点智能唤醒(含数据帧过滤技巧)

本文详细介绍了如何使用TJA1145A收发器实现CAN节点的智能唤醒功能,包括数据帧过滤技巧和超低功耗设计。通过硬件级帧过滤和双条件唤醒机制,TJA1145A在保持微安级休眠电流的同时,能对特定报文做出毫秒级响应,显著提升电池供电设备的续航能力。

weixin_28721917的博客 251

Bootloader详解,理解Bootloader看这篇就够了

这里写目录标题一、Bootloader作用(目的)二、完成Boot最终目的的前提条件三、对前提条件的详细说明3.1、对前提条件(1)的说明:3.2、对前提条件(2)的说明:3.3、对前提条件(3)的说明:3.4、对前提条件(4)的说明:3.4、对前提条件(5)的说明:四、loader是干啥的 一、Bootloader作用(目的) Bootloader=Boot + loader Boot的目的: 最终目的:跳到C语言中;为了C语言运行程序会进行一系列的初始化,系统一上电后如何通过一系列的设置让软件程序员

iduuigdg的博客 11万+

STL map迭代器误用记录

STL map迭代器误用记录 最近在项目中在编写一循环个释放map中元素时,在循环第二次的时候导致程序崩溃。代码如下: std::map<unsigned int, Rule*>::iterator mapRulesItor; for(mapRulesItor = m_mapRules.begin();mapRulesItor != m_mapRules.end();++mapRulesItor) { if(mapRulesItor->second != nullptr) {

u012368842的博客 330

【嵌入式笔试题】C语言笔试题(4)

嵌入式C语言综合笔试题

m0_74055118的博客 1067

QCreator + VS2010 生成MAP文件和COD文件

参考:http://blog.youkuaiyun.com/gwzz1228/article/details/9045853 需要在Pro文件里添加 win32:contains(QMAKE_CC, cl){ QMAKE_CXXFLAGS -= -Zc:wchar_t- QMAKE_CXXFLAGS += -Zc:wchar_t QMAKE_CXXFLAGS += -FAc

guomingbing12的专栏 2530

ASTRA Toolbox学习笔记-Python

ASTRA Toolbox 是一个用于处理 X 射线相干散射和 X 射线传输成像的开源算法工具箱。本文档概述了该工具箱的基本概念。

hou9021的博客 8261

别再死记硬背窗函数公式了!用MATLAB实战汉宁窗FIR滤波器,从频谱图看懂‘主瓣’和‘旁瓣’

本文通过MATLAB实战演示汉宁窗FIR滤波器的设计过程,帮助读者从频谱图直观理解主瓣与旁瓣的特性。文章详细对比了矩形窗与汉宁窗的频谱差异,并提供了高通滤波器设计的完整代码示例,适用于数字信号处理学习和工程应用。

weixin_30555125的博客 490

MS-VC 使用MAP文件快速定位程序崩溃代码行[转]

程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕,反而是测试的成功。我们更为关心的是程序中的哪一行导致了系统崩溃,这样我们才能有针对性的进行改正。  在VC中,我们可以利用出现程序崩溃时VC的自动跳转,定位到出错代码行。但在大量的压力

我的程序世界 1107

华为IC岗笔试刷题含答案(2)

又做了几套题,记录了部分及答案,如有错误,欢迎评论指正。

Ingrid的博客 1万+

[转]MS-VC 使用MAP文件快速定位程序崩溃代码行(转贴)

作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕,反而是测试的成功。我们更为关心的是程序中的哪一行导致了系统崩溃,这样我们才能有针对性的进行改正。 在VC中,我们可以利用出现程序崩溃时VC的自动跳转,定位到出错代码行。但在

魔笛的专栏 922

uniapp [全端兼容] - 详细实现拍照或相册选取图片后插入水印功能,手机拍照或相册上传图像并添加自定义水印及指定位置显示水印,uniApp给图片加水印后上传到后端服务器或保存到本机相册详细教程!

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,图片水印,上传照片带水印,从相册选择图片加水印功能,拍完照片给图片加水印,添加照片水印,uniapp图片加水印,为图片添加自定义水印,uni-app上传图片并添加水印,上传图片加水印,uni-app如何对拍摄的照片加水印,uni-app实现图片上传添加水印操作,给上传的图片添加上水印,图片加完水印后如何上传到服务器,水印相机,拍照图片加水印,相册选取后给图片加上水印,渲染失败,无法保存,文字水印,日期

🏆 前端领域优质创作者 1万+

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

MS-VC 使用MAP文件快速定位错误行 .

**********************************************************************************************************************************

QQIANQQ的专栏 2121

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

[转]VC生成MAP文件

[转]VC生成MAP文件   MS-VC 使用MAP文件快速定位程序崩溃代码行 收藏 作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕,反而是测试的成功。我们更为关心的是程序中的哪一行导致了系统崩溃,这样我们才能有针对性的

心之所向,身之所往 3709

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

MS-VC 使用MAP文件快速定位错误行

**********************************************************************************************************************************

hakuabby的专栏 646

转载——利用map文件调试程序崩溃

转载——利用map文件调试程序崩溃 http://blog.youkuaiyun.com/goodwinds/archive/2009/05/23/4211654.aspx From Wiki帮助系统 Jump to: navigation, search 2010年2月8日MS-VC 使用MAP文件快速定位程序崩溃代码行   程序员,平时最担心见到的事情就是程序发生了崩

善良的兽人 786

Linux 内核 Bug 排查实战:从 Oops 栈转储到精准定位缺陷代码行

内核 Bug 报告几乎都会附带一份像下图这样足以让人望而生畏的栈转储(stack dump),其中包含的 "Oops"、寄存器现场与函数调用链,其实足以帮助我们定位到缺陷发生的确切源码文件与行号。本文以 Linux 内核源码树中的 [bug-hunting.rst](https://link.gitcode.com/i/925cd718a2cbb4eca9aaa0b895c573e4) 为骨架,结

gitblog_00834的博客 1040

SilentPatch:GTA III / VC / SA 崩溃修复与兼容补丁使用指南

切到第二块屏幕的瞬间闪退、进出门黑屏卡死、高刷屏上 Alt+Tab 闪得眼晕——如果你正被这些老毛病卡住,先别急着重装游戏。SilentPatch 是一套专门给 GTA III、罪恶城(VC)和圣安地列斯(SA)做的崩溃修复与兼容补丁:它以 ASI 插件形式挂进游戏进程,处理二十年老代码在新系统上会踩的坑,不动核心玩法,你只需要放下一个文件就能开始用。 ## 一句话说清它是什么 SilentP

gitblog_01072的博客 655
上一篇: 线程同步之Win32API的Wait函数
下一篇: HOOK初步
amdk_7
博客等级 码龄22年 12粉丝 2原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值