现在的位置: 首页 > 综合 > 正文

如何根据异常提示信息找出程序出错代码(VC6)

2013年02月24日 ⁄ 综合 ⁄ 共 2095字 ⁄ 字号 评论关闭

看到网上说在debug下可以找到预料的崩溃地址行,但是实际上没有什么用呀。
(既然在debug下,那直接用调试器找不更好吗? 费这么大劲干什么)(转的文章在后面)

Release版本(指编译器优化后的),要找崩溃地址行就比较费劲了。
linux
下的方法:
1
、使之生成core dump文件
2
gdb调试该core文件
3
、根据大概的堆栈信息,运行disassemble (具体用法见gdb帮助)
4
、根据崩溃地址找到对应的崩溃反汇编码
5
、分析反汇编代码,找到程序中崩溃代码。
(如果用debug调试,就更简单了,步骤同上,编译的时候加上编译选项 -ggdb ,选项详情请见man g++

mac下的方法:
1.
、使之可以生成core 文件,方法同linux
2
、分析对应的crash log 在系统日志目录下。
3
、根据2的堆栈信息,反汇编,得到具体地址行。

最后转2win下的文章。(这种方法好像难找release的。)
(1)  
(vs2003
以上,vc6找对应设置就可以)

步骤一:编译代码时生成map 文件和 cod 文件

我建立了一个名为DataAbort的项目,A)生成map文件,打开项目属性对话框,找到链接--调试生成映射文件栏选择 B)生成cod文件,打开项目属性对话框,找到“C/C++--输出文件汇编输出栏选择带机器码的程序集

在默认情况下map文件以项目名称命名,而cod文件以cpp文件名命名,生成目录也不同,编译后可以在项目目录下搜索*.map *.cod

步骤二:根据异常信息找到相应的map文件,及异常地址所在的函数

步骤三:打开异常函数所在的cod文件,找到异常对应的代码行。分析问题,解决问题

 

(2)仅通过崩溃地址找出源代码的出错行一文的补充与改进

读了老罗的仅通过崩溃地址找出源代码的出错行”(下称"罗文")一文后,感觉该文还是可以学到不少东西的。不过文中尚存在有些说法不妥,以及有些操作太繁琐的地方。为此,本人在学习了此文后,在多次实验实践基础上,把该文中的一些内容进行补充与改进,希望对大家调试程序,尤其是release版本的程序有帮助。欢迎各位朋友批评指正。

一、该方法适用的范围
  在windows程序中造成程序崩溃的原因很多,而文中所述的方法仅适用与:由一条语句当即引起的程序崩溃。如原文中举的除数为零的崩溃例子。而笔者在实际工作中碰到更多的情况是:指针指向一非法地址 ,然后对指针的内容进行了,读或写的操作。例如:

void Crash1()
{
 char * p =(char*)100;
 *p=100;
}

  这些原因造成的崩溃,无论是debug版本,还是release版本的程序,使用该方法都可找到造成崩溃的函数或子程序中的语句行,具体方法的下面还会补充说明。另外,实践中另一种常见的造成程序崩溃的原因:函数或子程序中局部变量数组越界付值,造成函数或子程序返回地址遭覆盖,从而造成函数或子程序返回时崩溃。例如:

#include
void Crash2();
int main(int argc,char* argv[])
{
        Crash2();
        return 0;
}

void Crash2()
{
        char p[1];
        strcpy(p,"0123456789");
}

vc中编译运行此程序的release版本,会跳出如下的出错提示框。


图一 上面例子运行结果

  这里显示的崩溃地址为:0x34333231。这种由前面语句造成的崩溃根源,在后续程序中方才显现出来的情况,显然用该文所述的方法就无能为力了。不过在此例中多少还有些蛛丝马迹可寻找到崩溃的原因:函数Crash2中的局部数组p只有一个字节大小,显然拷贝"0123456789"这个字符串会把超出长度的字符串拷贝到数组p的后面,即*(p+1)=''1''*(p+2)=''2''* (p+3)=''3''*(p+4)=4。。。。。。而字符''1''ASC码的值为0x31''2''0x32''3'' 0x33''4''0x34。。。。。,由于intelcpuint型数据是低字节保存在低地址中,所以保存字符串''1234''的内存,显示为一个4字节的int型数时就是0x34333231。显然拷贝"0123456789"这个字符串时,"1234"这几个字符把函数Crash2的返回地址给覆盖,从而造成程序崩溃。对于类似的这种造成程序崩溃的错误朋友们还有其他方法排错的话,欢迎一起交流讨论。

二、设置编译产生map文件的方法
  该文中产生map文件的方法是手工添加编译参数来产生map文件。其实在vc6IDE中有产生map文件的配置选项的。操作如下:先点击菜单"Project"->"Settings。。。",弹出的属性页中选中"Link"页,确保在"category"中选中"General",最后选中"Generate mapfile"的可选项。若要在在map文件中显示Line numbers的信息的话 ,还需在project options 中加入/mapinfo:lines

抱歉!评论已关闭.