通过offset地址确定引起崩溃的代码行【俺想长点信誉分】

fisker0303 2005-12-07 01:15:53
简介
当release版本的程序交付给用户使用后,如果应用程序崩溃了,怎么样通过windows提示的offset地址来定位源程序中对应的出错代码呢?这篇文章就来讨论这个问题。

建立调试环境
1.(VC 6)依次选择FileàNewàProjects,在列表中选择“MFC AppWizard(EXE)”在“Project Name”中输入“Crash_Test”作为项目名,“OK”进入下一步。在“MFC Appwizard – Step 1”对话框中选择“Dialog Based”单选框。“Finish”完成工程的建立,F7编译无误。
2.(VC 6)双击确定按钮,提示加入(重写)“OnOK”函数,OK,进入“CCrash_TestDlg::OnOK()”函数。
3.我们将在OnOK函数中构造一些能够引起程序崩溃的错误代码:
void CCrash_TestDlg::OnOK()
{
AfxGetApp()->GetMainWnd()->SetWindowText(_T("Crash"));
int* pTest = NULL;
*pTest = 0; // 为空指针赋值,程序将崩溃
CDialog::OnOK();
}
加入“AfxGetApp()->GetMainWnd()->SetWindowText(_T("Crash"));”的目的是使崩溃地址和“OnOK”的地址有一定偏移,使演示更具一般性。
4.(VC 6)首先设置Release编译(在BuildàSet as configuration中选择Win32 Release)。依次选择ProjectàSettings,选择“C/C++”tab页,Category中选择“Listing Files”,然后在“Listing file type”中选择“Assembly, Machine Code, and Source”,OK。这个选项将为每个源文件(*.cpp)生成机器码、汇编码和源代码的对应表,可以在“Release”目录下找到和查看这些文件。
5.(VC 6)依次选择ProjectàSettings,选择“Link”tab页,Category中选择“Debug”,
钩选“Generate map file”,OK。这个选项将生成编译后的函数地址和函数名的对应表。

定位错误代码
1.现在运行“Release”目录下的测试程序,当点击“确定”按钮时,程序将崩溃。
Windows XP 会出现
“Crash_Test.exe 遇到问题需要关闭。我们对此引起的不便表示抱歉。”…………
云云的对话框,在对话框的下方,单击“请单击此处”的超连接,在“错误签名”中,我们会得到如下信息:
AppName: crash_test.exe AppVer: 1.0.0.1 ModName: crash_test.exe
ModVer: 1.0.0.1 Offset: 000014a0
其中的Offset值就是崩溃的地址啦,现在我们根据这个地址来定位源程序中出错的代码行。
2.用记事本打开“Release”目录下的,“Crash_Test.map”文件,在文件中会看到类似下面的内容:
0001:00000470 ?OnQueryDragIcon@CCrash_TestDlg@@IAEPAUHICON__@@XZ 00401470 f Crash_TestDlg.obj
0001:00000480 ?OnOK@CCrash_TestDlg@@MAEXXZ 00401480 f Crash_TestDlg.obj
0001:000004c0 ?BeginModalState@CWnd@@UAEXXZ 004014c0 f i Crash_TestDlg.obj
0001:000004d0 ?EndModalState@CWnd@@UAEXXZ 004014d0 f i Crash_TestDlg.obj
画线的部分就是各个函数编译运行后在内存中的相对地址 (高位部分是基地址,就不参与计算啦,基地址可能因机器不同而异,但相对地址都是一样的。) ,因为“Offset”指示的崩溃地址为“14a0”,
1480(OnOK地址) < 14a0(出错地址) < 14c0(BeginModalState地址),很显然,14a0的地址是在OnOK函数的地址范围内的,也就是说OnOK就是引起崩溃的函数。接下来再来确定出错的具体代码行。
3.因为OnOK是在“Crash_TestDlg.cpp”中实现的,因此,我们打开对应的“Crash_TestDlg.cod”文件,其中有如下代码:
?OnOK@CCrash_TestDlg@@MAEXXZ PROC NEAR ; CCrash_TestDlg::OnOK, COMDAT
; 173 : {
00000 56 push esi
00001 8b f1 mov esi, ecx
… …
; 175 : int* pTest = NULL;
; 176 : *pTest = 0;
; 177 : CDialog::OnOK();
0001e 8b ce mov ecx, esi
00020 c7 05 00 00 00 00 00 00 00 00 mov DWORD PTR ds:0, 0
0002a e8 00 00 00 00 call ?OnOK@CDialog@@MAEXXZ ; CDialog::OnOK
0002f 5e pop esi
; 178 : }
… …
很明显,这些就是OnOK函数的汇编表示和机器码表示,画线的地址就是函数中各个语句的相对(相对于函数首地址)地址。
在步骤1中,我们已经得到,Offset为14a0,OnOK的函数首地址为0480,现在,我们用14a0-1480就得到20(注意,这里都是16进制运算),可见,出错的代码行为:
00020 c7 05 00 00 00 00 00 00 00 00 mov DWORD PTR ds:0, 0
对应上面注释的:
; 176 : *pTest = 0;

...全文
266 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
DoItFreely 2005-12-07
  • 打赏
  • 举报
回复
生成map文件就好了。里面有函数和地址的对照表,根据offset就能查到它落在哪个函数内。再用调试工具调试(debug/release版)的程序,找到该offset就是了
fisker0303 2005-12-07
  • 打赏
  • 举报
回复
NO,我参照了一些文章重新写的,这个是step by step的,可以一步一步跟着做,希望给大家带来些帮助。
hjunxu 2005-12-07
  • 打赏
  • 举报
回复
虽然在很多地方看见,但还是感谢楼主。

顺便接分。
Atomictry 2005-12-07
  • 打赏
  • 举报
回复
再继续呢...,愈多愈好。
lvgame 2005-12-07
  • 打赏
  • 举报
回复
学习。
sunj_study 2005-12-07
  • 打赏
  • 举报
回复
收到,多谢楼主。

怎么帮你加信誉分?
fisker0303 2005-12-07
  • 打赏
  • 举报
回复
4.(VC 6)首先设置Release编译(在BuildàSet as configuration中选择Win32 Release)。依次选择Project-->Settings,选择“C/C++”tab页,Category中选择“Listing Files”,然后在“Listing file type”中选择“Assembly, Machine Code, and Source”,OK。这个选项将为每个源文件(*.cpp)生成机器码、汇编码和源代码的对应表,可以在“Release”目录下找到和查看这些文件。
sunj_study 2005-12-07
  • 打赏
  • 举报
回复
请问楼主如何设置生成.cod文件?

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧