编程序最怕的就是报内存错误,而这种错误又是经常出现的,当错误发生在debug下时可以通过调试找到错误所在,而在release下则不可以,这时可以利用map文件定位到发生错误的语句。注意不要相信在release下报错后进行调试所指向的错误所在。 首先设定能生成map文件 项目---属性---配置属性---连接器---调试下,生成映射文件:是(/MAP) 映射文件名:$(IntDir)/XXX.map ,一个工程生成一个map文件 设置生成cod文件 项目--属性----配置属性---C/C++---输出文件下,汇编输出:程序集、机器码和源代码(/FAcs)。一个cpp文件生成一个cod文件。 重新生成解决方案后可在release文件夹下看到生成的map文件和cod文件。 下面说名如何通过这两种文件找到错误所在。 简单例子: (1) #include "stdafx.h" void errorFun(int * p) int _tmain(int argc, _TCHAR* argv[]) 在errorFun中函数中,*p=1这一行出错,由于p没有申请空间,运行时出错,弹出Unhandled exception at 0x004113b1 in testError.exe: 0xC0000005: Access violation writing location 0x00000000.在0x004113b1程序发生崩溃。
打开map文件,定位崩溃函数. map文件开头是一些链接信息,然后我们要找函数和实始地址信息。地址是函始的开始地址 Address Publics by Value Rva+Base Lib:Object 0000:00000000 ___safe_se_handler_count 00000000 <absolute> ....
程序崩溃地址0x004113b1,我们找到第一个比这个地址大的004113d0,前一个是00411390,地址是函数的开始地址,所以发生的崩溃的的函数是errorFun,这个函数的初始地址00411390.
通过cod文件找出具体崩溃行号. 由(2)可知,发生错误函数是errorFun,在testError.obj,打开testError.cod文件,找到errorFun函数生成的机器码. errorFun@@YAXPAH@Z PROC ; errorFun, COMDAT ; 7 : { 00000 55 push ebp
; 8 : *p=1; 0001e 8b 45 08 mov eax, DWORD PTR _p$[ebp]
; 9 : } 00027 5f pop edi
我们计算相对偏移地址,即崩溃地址-函数起始地址,0x004113b1-0x00411390=0x21(16进制的计数)找到0x21这一行对应的机器码是 00021 c7 00 01 00 00,向上看它是由第8行*p=1;生成的汇编码,由此可见是这一行程序发生崩溃。 这样就找到了报内存错误的罪魁祸首了。 |
|