发布时间:2014-12-31 16:06
分类名称:Debug_Crack
调试问题
我们在解决Bug的时候经常遇到一些难重现的Bug。例如偶尔崩溃的问题,如果错失现场,也许花几天时间也难重现,最后不了了之。在发布后,可能在客户那里重新出现,这种Bug很让人懊恼。
如果我们能掌握一些Release模式下的调试技巧,事情就会变的简单起来。将调试时间从几天降低到数小时内。一般在程序崩溃后,可以用一些工具(典型 的:WinDbg)将其dump文件获取出来,拿到我们开发机器上进行分析。通常获取的都是Release版本的dump文件,使用 VS2008,Windbg都能打开来分析。初次打开,你会发现崩溃的调用堆栈,但是堆栈都是一堆不可识别的符号,分析难度很大,如果我们保留了模块对应的PDB文件,使用调试软件加载,就能够定位到具体的崩溃位置。
PDB知识
PDB文件是微软编译器产生出来的,专门为了调试使用的。微软的操作系统里大部分模块对应的PDB文件,都能通过微软的在线服务器下载得到:
http://msdl.microsoft.com/download/symbols
PDB中包含什么东西都?
调试器如何配对正确的PDB?
1. 模块的名字。例如一个模块叫XXX.DLL,调试器就会找XXX.PDB。 2. 如何判断此PDB是否和模块相对应? 调试器在编译的时候,会给XXX.DLL模块中插入一个GUID,PDB文件中也有一个GUID。这两个GUID只有相同,调试器才会加载此PDB。
GUID这个数值和机器,时间等因素有关。即便我们没有更改一行代码,每次重新编译后的此值都会变化。所以,保存当时对应的PDB尤为重要。
使用VS2008的DUMPBIN.exe工具,你就能够找到这个GUID:
>>dumpbin.exe /HEADER HelloWorld.exe
Debug Directories
Time Type Size RVA Pointer
-------- ------ -------- -------- --------
4A03CA66 cv 4A 000025C4 7C4 Format: RSDS,
{4B46C704-B6DE-44B2-B8F5-A200A7E541B0}, 1,
C:\junk\stuff\HelloWorld\obj\Debug\HelloWorld.pdb
Windbg工具包里附带了一个工具:symchk.exe.可以用来检测PDB和模块是否匹配:
symchk RinjPlay.exe /s .\
如果匹配:
SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 1
如果不匹配:
SYMCHK: RinjPlay.exe FAILED - RinjPlay.pdb mismatched or not found
SYMCHK: FAILED files = 1
SYMCHK: PASSED + IGNORED files = 0
调试器如何查找PDB?
注:不同编译器查找的顺序可能会不同
我们平常调试的时候,模块一般在哪儿,都将对应的pdb拷贝到相同目录下。
产生PDB文件后,模块也随之变大?
VS2008编译Release版本,默认是不产生PDB文件的。如果要产生PDB文件,需要几个步骤:
第一步,设置Debug Information Format为Program Database(/Zi),也就是给cl.exe加/Zi参数。
第二步,给link.exe 加/DEBUG参数:
经过这两个步骤后,PDB文件就产生出来了,但你会发现我们的模块也随之变大。这是因为我们打开了/DEBUG开关,Link.exe不会做任何优化,编译出的Obj中函数可能有300多个,而我们引用的可能只有5个,但/DEBUG开关打开,300的函数都会被连接进去。所以我们要告诉链接器不要 连接没有被引用的文件:
第三步,优化:
再次编译,模块大小又缩小回去了,甚至比一开始不产生PDB文件时还小。
更多内容
关于PDB以及调试技巧的更多知识,参考这里:
http://blog.163.com/hao_dsliu/blog/#m=0&t=1&c=fks_084071092095085074092080083095085085080070083094095067092