如果程序崩溃,我们可以根据windows提供的crash address,利用map文件快速的找到导致程序崩溃的原因(出问题的函数,出问题的代码行)。本文通过一个Visual C++ 6.0示例项目讲解如何利用map文件快速找到导致程序crack的bug。
创建map文件。
新建一MFC Dialog based exe项目,将项设定为release版本,并在Project->Setting的c/c++栏中的for Debug Info选择”Line Numbers Only”。在link栏中,选中Generate mapfile,并在Project Option框中输入/MAPINFO:LINES 和/MAPINFO:EXPORTS 。之后编译,即会生成map文件在release文件夹下。
我们在该dialog上添加一个按钮,并为其添加点击事件OnButton1。在OnButton1中添加一段会导致程序崩溃的代码。
char* pEmpty = NULL;
*pEmpty = 'x';
如何寻找出错代码行
点击运行,程序崩溃后,在windows 的错误提示对话框中找到crash address.
在本例中,crash address为0x401480。
之后,用ultra edit之类的文本编辑器打开map文件,查找4014(为的是找到第一个>=crash addess的地址)。结果找到:
0001:00000480 ?OnButton1@CMapFileTestDlg@@IAEXXZ 00401480 f MapFileTestDlg.obj
即可以依此来判断出问题的函数就是这个: ?OnButton1@CMapFileTestDlg@@IAEXXZ
如果安装过ms .net, 在vc7/bin目录下,有一个名为UNDNAME.EXE的工具,利用它可解析出其原名。Undname.exe ?OnButton1@CMapFileTestDlg@@IAEXXZ。得到结果为:
Undecoration of :- "?OnButton1@CMapFileTestDlg@@IAEXXZ"
is :- "protected: void __thiscall CMapFileTestDlg::OnButton1(void)"
可知出问题的函数是CMapFileTestDlg类的OnButton1方法。
最后,我们要获得bug的代码行在哪儿。先计算crash_address - preferred_load_address - 。 0x1000
在本例中为:0x401480 – 0x400000 – 0x1000 = 0x480
因为在上面我们已经知道问题出在CMapFileTestDlg类中,即文件MapFileTestDlg.cpp中之后,所以找到该段
Line numbers for ./Release/MapFileTestDlg.obj(F:/MapFileTest/MapFileTestDlg.cpp) segment .text
在该段中查找第一个>=该地址的地址。开头的第一个字段即为出错行数。
本例中为:174 0001:00000480。即第174行出错。
关于map文件的详细说明,请查阅MSDN.
附:在VC++.NET中,同样可以使用。使用方法:
项目属性->C/C++->常规->调试信息格式:仅限行号(/Zd)
连接器->命令行->附加选项输入:
/map:"Release/Map文件名.map" /MAPINFO:LINES /MAPINFO:EXPORTS
|