前言:利用drwtsn32或NTSD进行程序崩溃处理,都可以生成可用于调试的dmp格式文件。使用VS2005打开生成的DMP文件,能很方便的找出BUG所在位置。本文将讨论以下内容:
1、 程序编译选项
2、 利用VS2005 分析dump文件
3、 常见问题讨论
一、 程序编译选项
PDB files contains all debug information like type definition and function prototype. When application crashes, we need the PDB files to analyze the root cause, so make sure these PDB files will be created when building it. You must do the following setting:
C/C++/General/Debug Information Format=Program Database (/Zi).
![clip_image001 clip_image001](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image001_thumb.jpg)
图1.1 调试信息格式
Linker/Debugging/Generate Program Database File=”Name and location of your PDB files”
![clip_image002 clip_image002](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image002_thumb.jpg)
图1.2 PDB文件输出路径
PDB文件路径最好设置在同一个文件夹中,这样方便dmp文件调试时调用。
调试时,所有的PDB文件和源文件必须严格匹配(the PDB files should be the one generated by build the source code),并存储在一个安全的位置。当客户报告了一个错误时,你需要这些文件来帮忙以便定位错误于源代码中并解决问题。
二、 VS2005 分析dump文件
In this simple application, there is an unhandled Access Violation Reading exception, because GetNameFromDatabase returns a NULL pointer, and this pointer is passed into IsPrefix and then it’s used directly without NULL pointer checking.
![clip_image003 clip_image003](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image003_thumb.jpg)
图1.3 演示代码
利用Release模式编译该测试程序,在客户机上运行该程序,将根据NTSD设置生成相对应的DMP格式文件。
可以使用Visual Studio.Net、NTSD或是其他的调试工具对DMP格式文件进行分析。
l Start Visual Studio.Net
Click File/Open Solution and make sure the files of type is *.dmp then click Open.
![clip_image004 clip_image004](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image004_thumb.jpg)
图1.3 Open Dump File (GUI)
l Set Symbol Path
Click Tools/Options, Debugging/Symbols,增加PDB文件路径。若调试的程序需要微软基础库的PDB信息,可以增加一个路径为:
http://msdl.microsoft.com/download/symbols
在界面下方Cache Symbol From symbol…选择本地存储这些Symbols的路径。
![clip_image005 clip_image005](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image005_thumb.jpg)
图1.4 Symbol Path
如果DMP文件没有放入本身PDB文件所在目录,也可以在此处增加一个本地目录。点OK后,VS2005将从网络中下载所需要的Symbols,需要等待一段时间。如果是多次调试同一个程序错误所生成的DMP文件,可以在对话框中选择“Search the above locations only when symbols are loaded manually”。从而可以节省网络带宽。
l Set Source code path
Open Solution Property Pages and set the source code path.
![clip_image006 clip_image006](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image006_thumb.jpg)
图1.5 属性菜单
![clip_image007 clip_image007](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image007_thumb.jpg)
图1.6 Debug Source Files
l Start to Debug the Dump File
Click the Debug menu, it will ask you to save as a solution, save it. Then it will go to the line which caused the crash of your application.
![clip_image008 clip_image008](http://www.cppblog.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/VS2005dump_10A8C/clip_image008_thumb.jpg)
图1.7 调试窗口,定位到源代码
三、 常见问题讨论
1、 Dump文件放在哪里?
Dump文件不用非要放在你编译出来的位置,你完全可以建立一个新的文件夹来放它。但若不是存放在编译出来的位置,需要将编译生成的PDB文件拷贝到Dump文件目录,或是利用VS2005打开Dump文件后,设置PDB文件路径。参照图1.4。
2、 如何恢复当时的现场?
可能你要问,怎么可能,这个dump文件可是用户发给我的,我不可能去用户家里调试吧?这个恢复现场可不是指的非要到那台机器上去,而是要把产生dump文件对应的二进制文件拿到。
但是恢复现场需要所有的二进制文件都要对应,你一定要有导致用户崩溃的那些Exe和DLL。既然是你发布的程序,Exe文件当然你会有。所以这里只考虑DLL就行了。
Dump文件中记录了所有DLL文件的版本号和时间戳,所以你一定可以同过某种途径拿到它。如果你能从用户那里拿到最好,如果不方便,用户不可能用的是我们平常不常用的操作系统,所以找个有对应系统的机器一般都会有。但是记住不仅是文件名称要一致,还要核对版本和时间戳,如果不同一样没有办法用。
如果客户用了某个特殊的补丁怎么办?
其实这个问题也很好解决,只要它不阻碍阅读堆栈,就不用管它,调试Dump和运行程序不一样,缺少一两个DLL没有任何问题。
3、 如果真的需要怎么办?
符号文件现在主要是指PDB文件。
如果没有符号文件,那么调试的时候可能导致堆栈错误。
如果你丢失了这个发布版本中你编译出来的那些exe和DLL的PDB,那么这个损失是严重的,重新编译出来的版本是不能使用的。
我自己的DLL都有了,可是缺的是系统的DLL的对应PDB文件怎么办?图1.4中已经介绍了方法。微软在它的符号数据库上为我们提供了所有的PDB文件,还有部分非关键DLL。设置好后程序将自动下载需要的PDB及DLL文件。
4、 拿到需要的文件了,这些文件应该放在哪里?
符号数据库中的文件不用动,把其它的exe和DLL、PDB文件放在dump文件目录里就行了。
5、 我用的是VS2005,明明有源代码,为什么显示不了?
这个是dump调试的最头痛问题,代码可能已经改过了,即使你从SVN拿到当时的版本,时间戳也是错的,VS2005就是不让你显示代码。其实只要在
Tools/Options,Debugging/General中去掉
Require source files to exactly match the original version的复选就行了。