截取自《游戏之旅——我的编程感悟》P311, 作者:云风
PS:
最近在项目中正好遇到一个release版本在测试部门崩溃了,正好拿来练手。由于是第一次,折腾了一个多小时才定位到问题。这里去把一些心得写下来。
1、崩溃时,windows会弹出一个对话框,告诉你哪个地址发生了什么样的错误。通常这还不够,dump文件更有用。dump文件生成的方法有很多,可以用代码,xp下有Dr.Watson(drwtsn32),win7更方便,任务管理器就可以了。如果那台机器正好有装vs,直接拿来调试(没有vs也没关系,可以马上用windbg附加上即可,当然最好有符号资源)
2、崩溃的地方是我的一个dll里面的,跳转到栈区看。VS显示的栈的地址是崩溃的位置,不是当前函数的位置。所以正确的函数应该是当前位置往前的第一个。
举个例子:假设崩溃的位置是 0x748c33ef,我的dll映射的范围是0x74c8c000-0x748c9000,那么实际偏移是0x748c33ef-0x748c000 = 0x33ef。我的map文件里有下面的记录
0001:000023dd _atexit 100033dd f MSVCRT:atonexit.obj
0001:000023f4 _XXXX 100033f4 f MSVCRT:XXXXX.obj
那么可以断定它是在_atexit里面出问题不。
3、下一步是准确找到准确的位置。如果你熟悉汇编,当然可以直接阅读即可。这里在开发机上直接调试发行版的dll,可以看到汇编和源代码的对应关系。
这里调试的目标的版本很重要,如果现有的工程环境已变,那么对应的map和目标码肯定也不一样了。我的做法是在发行的dll的版本号标记为svn上的版本号,到时候只有checkout对应的版本即可精确重现。