作为程序员,我们平时最担心见到的事情是什么?是内存泄漏?是界面不好看? ……错啦!我相信我的看法是不会有人反对的——那就是,程序发 生了崩溃!
“该程序执行了非法操作,即将关闭。请与你的软件供应商联系。 ”,呵呵,这句 M$ 的“名言”,恐怕就是程序员最担心见到的东西了。有 的时候,自己的程序在自己的机器上运行得好好的,但是到了别人的机器上就崩溃了;有时 自己在编写和测试的过程中就莫名其妙地遇到了非法操作,但是却无法确定到底是源代码中 的哪行引起的……是不是很痛苦呢?不要紧,本文可以帮助你走出这种困境, 甚至你从此之后可以自豪地要求用户把崩溃地址告诉你,然后你就可以精确地定位到源代码 中出错的那行了。(很神奇吧?呵呵。)
首先我必须强调的是,本方法可以在目前市 面上任意一款编译器上面使用。但是我只熟悉 M$ 的 VC 和 MASM ,因此后面的部分只介绍 如何在这两个编译器中实现,请读者自行融会贯通,掌握在别的编译器上使用的方法。
Well,废话说完了,让我们开始! :)
首先必须生成程序的 MAP 文件。什 么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号、源文件和代码行号信息的唯一的 文本表示方法,它可以在任何地方、任何时候使用,不需要有额外的程序进行支持。而且, 这是唯一能找出程序崩溃的地方的救星。
好吧,既然 MAP 文件如此神奇,那么我们 应该如何生成它呢?在 VC 中,我们可以按下 Alt+F7 ,打开“Project Settings”选项页,选择 C/C++ 选项卡,并在最下面的 Project Options 里面输入: /Zd ,然后要选择 Link 选项卡,在最下面的 Project Options 里面输入: /mapinfo:lines 和 /map:PROJECT_NAME.map 。最后按下 F7 来编译生成 EXE 可执行文件和 MAP 文件。
在 MASM 中,我们要设置编译和连接参数,我通常是这样做的:
rc %1.rc
ml /c /coff /Zd %1.asm
link /subsystem:windows /mapinfo:exports /mapinfo:lines /map:%1.map %1.obj %1.res
把它保存成 makem.bat ,就可以在命令行输入 makem filename 来编译生成 EXE 可执行文件和 MAP 文 件了。
在此我先解释一下加入的参数的含义:
/Zd 表示在编译的时候生成行 信息
/map[:filename] 表示生成 MAP 文件的路径和文件名
/mapinfo:lines 表示生成 MAP 文件时,加入行信息
/mapinfo:exports 表示生成 MAP 文件时,加入 exported functions (如果生成的是 DLL 文件,这个选项就要加上)
OK,通过上面 的步骤,我们已经得到了 MAP 文件,那么我们该如何利用它呢?
让我们从简单的实 例入手,请打开你的 VC ,新建这样一个文件:
01 //****************************************************************
02 //程序 名称:演示如何通过崩溃地址找出源代码的出错行
03 //作者:罗聪
04 //日期 :2003-2-7
05 //出处:http://www.luocong.com(老罗的缤纷天地)
06 //本 程序会产生“除0错误”,以至于会弹出“非法操作”对话框。
07 //“除0错误”只会在 Debug 版本下产生,本程序为了演示而尽量简化。
08 //注意事项:如欲转载,请保持本程序的完整,并注明:
09 //转载自 “老罗的缤纷天地”(http://www.luocong.com)
10 //****************************************************************
11
12 void Crash(void)
13 {
14 int i = 1;
15 int j = 0;
16 i /= j;
17 }
18
19 void main(void)
20 {
21 Crash();
22 }