您的位置:逆风者 VC++ 正文
 添加时间:2007-09-01 原文发表:2007-08-31 人气:59 来源:vckbase.com

本文章共6237字,分4页,当前第1页,快速翻页:
 

对“仅通过崩溃地址找出源代码的出错行”一文的补充与改进

作者:上海伟功通信 roc

下载源代码
逆风者

  读了老罗的“仅通过崩溃地址找出源代码的出错行”(下称"罗文")一文后,感觉该文还是可以学到不少东西的。不过文中尚存在有些说法不妥,以及有些操作太繁琐的地方 。为此,本人在学习了此文后,在多次实验实践基础上,把该文中的一些内容进行补充与改进,希望对大家调试程序,尤其是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。。。。。,由于intel的cpu中int型数据是低字节保存在低地址中 ,所以保存字符串''1234''的内存,显示为一个4字节的int型数时就是0x34333231。显然拷贝"0123456789"这个字符串时,"1234"这几个字符把函数Crash2的返回地址给覆盖 ,从而造成程序崩溃。对于类似的这种造成程序崩溃的错误朋友们还有其他方法排错的话,欢迎一起交流讨论。


二、设置编译产生map文件的方法
  该文中产生map文件的方法是手工添加编译参数来产生map文件。其实在vc6的IDE中有产生map文件的配置选项的。操作如下:先点击菜单"Project"->"Settings。。。",弹出的属性页中选中"Link"页 ,确保在"category"中选中"General",最后选中"Generate mapfile"的可选项。若要在在map文件中显示Line numbers的信息的话 ,还需在project options 中加入/mapinfo:lines 。Line numbers信息对于"罗文"所用的方法来定位出错源代码行很重要 ,但笔者后面会介绍更加好的方法来定位出错代码行,那种方法不需要Line numbers信息。


图二 设置产生MAP文件


三、定位崩溃语句位置的方法
  "罗文"所述的定位方法中,找到产生崩溃的函数位置的方法是正确的,即在map文件列出的每个函数的起始地址中,最近的且不大于崩溃地址的地址即为包含崩溃语句的函数的地址 。但之后的再进一步的定位出错语句行的方法不是最妥当,因为那种方法前提是,假设基地址的值是 0x00400000 ,以及一般的 PE 文件的代码段都是从 0x1000偏移开始的 。虽然这种情况很普遍,但在vc中还是可以基地址设置为其他数,比如设置为0x00500000,这时仍旧套用
 
本文章更多内容1 - 2 - 3 - 4 - 下一页>>
相关文章

ATL 实现定制的 IE 浏览器栏、工具栏和桌面
乱砍设计模式之二:STATE 模式——履胡之肠
点对点视频会议程序:VideoNet
系统托盘编程完全指南(一)
枚举声明,模板函数特化
COM 组件注册方法
关于SendMessage
初试驱动---OV511 摄像头驱动开发
定制编辑框的上下文菜单
ATL布幔之下的秘密(5)
COM插件模型浅谈
Windows 2000驱动程序的设计
MFC 编写的仿 Windows 计算器
用VC实现支持多语言的程序
连接 COM 与.NET 的桥梁(二)——COM 服务
浅谈PDFlib中文输出(一)如何使用Acrobat标
代号 WinFS:革命性的文件存储系统...
使用 LIBCTINY.LIB 为 EXE 和 DLL 文件 减肥
树视控件在多文档中的使用
如何简单实现可执行文件的自我删除

相关评论


本文章所属分类:首页 VC++

  热门关键字: