文件生成方式:
在 VC 中,我们可以按下 Alt+F7 ,打开“Project Settings”选项页,选择 C/C++ 选项卡,并在最下面的 Project Options 里面输入:/Zd ,然后要选择 Link 选项卡,在最下面的 Project Options 里面输入: /mapinfo:lines 和 /map:PROJECT_NAME.map 。最后按下 F7 来编译生成 EXE 可执行文件和 MAP 文件。
文件格式:
DllTwo //―――模块名
Timestamp is 4956e425 (Sun Dec 28 10:27:49 2008) //―――时间戳
Preferred load address is 10000000 //―――默认加载基地址
Start Length Name Class //各节的起始地址、长度、
0001:00000000 00000da6H .text CODE //节名、类型等信息
0001:00000db0 00000053H .text$x CODE
0002:00000000 000000e8H .idata$5 DATA
0002:000000e8 00000004H .CRT$XCA DATA
……
0002:00000100 000000b0H .rdata DATA
……
0002:0000045c 00000782H .idata$6 DATA
0002:00000be0 00000094H .edata DATA
0003:00000000 00000014H .data DATA
0003:00000018 00000354H .bss DATA
//各符号在节内的偏移地址、加载地址及符号出处
Address Publics by Value Rva+Base Lib:Object
0000:00000003 ___safe_se_handler_count 00000003 <absolute>
0000:00000000 ___ImageBase 10000000 <linker-defined>
0001:00000000 ??4CDllTwo@@QAEAAV0@ABV0@@Z 10001000 f i DllTwo.obj
……
0001:00000804 __DllMainCRTStartup@12 10001804 f MSVCRT:crtdll.obj
……
0001:00000cd0 ?CrashFun@@YAHXZ 10001cd0 f DllTwo.obj
0001:00000cf0 _DllMain@12 10001cf0 f DllTwo.obj
0001:00000d00 ?PrintInDllTwo@@YAHXZ 10001d00 f DllTwo.obj
entry point at 0001:00000804 //模块的入口地址
Static symbols //静态符号
0001:00000463 __catch$??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z$0 10001463 f i CIL library: CIL module
0001:000004de _pre_c_init 100014de f MSVCRT:crtdll.obj
0001:000006ee ___DllMainCRTStartup 100016ee f MSVCRT:crtdll.obj
0001:00000db0
……
Exports //导出符号
ordinal name //序号和名称
1 ??4CDllTwo@@QAEAAV0@ABV0@@Z (public: class CDllTwo & __thiscall CDllTwo::operator=(class CDllTwo const &))
2 ?CrashFun@@YAHXZ (int __cdecl CrashFun(void))
3 ?PrintInDllTwo@@YAHXZ (int __cdecl PrintInDllTwo(void))
测试方式:
写一个程序,编译出来:
#include <stdio.h>
int main(){
int i = 2;
int j ;
scanf("%d",&j);
i = 2;
i = 3;
i = 4;
i = 5;
i = 6;
printf("%d",i/j);
return 0 ;
}
然后打开MAP文件.
里面有各种全局符号,大概在文件的中间位置,有这样的东西:
Line numbers for .\Debug\4.obj(E:\pro\4\4.cpp) segment .text
3 0001:00000010 4 0001:00000024 6 0001:0000002b 7 0001:0000003c
8 0001:00000043 9 0001:0000004a 10 0001:00000051 11 0001:00000058
可以直接Ctrl+F找到程序文件名,我这里是4.cpp
这些就是代码偏移和对应的行号.
三.调试
就刚才的程序,运行,输个0,过一下出错框就来了,
我是VISTA,下面的详细信息是:
问题签名:
问题事件名称: APPCRASH
应用程序名: 4.exe
应用程序版本: 0.0.0.0
应用程序时间戳: 499d5ade
故障模块名称: 4.exe
故障模块版本: 0.0.0.0
故障模块时间戳: 499d5ade
异常代码: c0000094
异常偏移量: 00001063
OS 版本: 6.0.6001.2.1.0.768.3
区域设置 ID: 2052
其他信息 1: 38fc
其他信息 2: db4f9c1c160faa4608f429ddffa01d6f
其他信息 3: cb3b
其他信息 4: e8ffb2a21d4a9ed7b258f1866c9d3db8
这个偏移就是要看的了。减去1000的代码段偏移。
就是63,再对照上面的行号和地址的列表
11 0001:00000058
这个是VC翻译的时候,第11行显然会对应多条指令。
这一指令群的开始地址是58.
这个是最接近63且比63小的地址,所以问题应该出在这一行上。
再看代码:
printf("%d",i/j);
发现这里有个除0错误。