pdb文件包含了编译后程序指向源代码的位置信息,用于调试的时候定位到源代码,主要是用来方便调试的。
在程序发布为release模式时,建议将 pdb文件删除, 同时,对外发布的时候,也把 pdb删除,有利于保护程序。php
PDB:Program Debug Database(程序调试数据库)文件
PDB(程序调试数据库)文件保持着调试和项目状态信息,从而能够对程序的调试配置进行增量连接。当用 /ZI 或 /Zi 编译 C/C++ 程序时或用 /debug 编译 Visual Basic/C# 程序时将建立 PDB 文件。
在 Visual C++ 中,/Fd 选项用于命名由编译器建立的 PDB 文件。当在 Visual Studio 中使用向导建立项目时,/Fd 选项将被设置以建立名为 project.PDB 的 PDB。 若是使用生成文件建立 C/C++ 应用程序,并指定 /ZI 或 /Zi 而不指定 /Fd 时,则最终将生成两个 PDB 文件: VC70.PDB(更笼统地说就是 VCx0.PDB,其中 x 表示 Visual C++ 的版本。)该文件存储各个 OBJ 文件的全部调试信息并与项目生成文件驻留在同一个目录中。
project.PDB 该文件存储 .exe 文件的全部调试信息。对于本机代码,它驻留在 \debug 子目录中。对于托管代码,它驻留在 \WINDEBUG 子目录中。程序员
定义: 生成类库项目时除了生成dll文件外,还会生成一个同名的pdb文件,它是一个程序数据库文件,保存着调试和项目状态信息,使用这些信息能够对程序的调试配置进行增量连接。 理解:pdb文件包含了编译后程序指向源代码的位置信息,用于调试的时候定位到源代码,主要是用来方便调试的。
在程序发布为release模式时,建议将 pdb文件删除, 同时,对外发布的时候,也把 pdb删除,有利于保护程序。 扩展:生成类库项目时不生成pdb文件:打开类库项目属性页面→切换到生成选项卡→点击高级按钮→将调试信息一项设置为none。 OK,继续搞代码。。。web
PDB文件:每一个开发人员都必须知道的
一 什么是PDB文件数据库
大部分的开发人员应该都知道PDB文件是用来帮助软件的调试的。可是他到底是如何工做的呢,咱们可能并不熟悉。本文描述了PDB文件的存储和内容。同时还描 述了debugger如何找到binay相应的PDB文件,以及debugger如何找到与binay对应的源代码文件。本文适用于全部的Native和 Managed的开发人员。 缓存
在开始前,咱们先定义2个术语:private build, 用来表示在开发人员本身机器上生成的build;public build,表示在公用的build机器上生成的build。private build相对来讲比较简单,由于PDB和binay在相同的地方,一般地咱们遇到的问题都是关于public build。
全部的的开发人员须要知道的最重要的事情是”PDB文件跟源代码一样的重要“, 没有PDB文件,你甚至不能debugging。对于public build,须要symbol server存储全部的PDB,而后当用户报告错误的时候,debugger才能够自动地找到binay相应的PDB文件, visual studio 和 windbg都知道如何访问symbol server。在将PDB和binay存储到symbol server前,还须要对PDB运行进行source indexing, source indexing的做用是将PDB和source关联起来。
接下来的部分假设有已经设置好了symbol server和source server indexing。TFS2010中能够很简单地完成对一个新的build的source indexing 和 symbol server copying。
服务器
二 PDB文件的内容app
正式开始PDB的内容,PDB不是公开的文件格式,可是Microsoft提供了API来帮助从PDB中获取数据。
Native C++ PDB包含了以下的信息:
* public,private 和static函数地址;
* 全局变量的名字和地址;
* 参数和局部变量的名字和在堆栈的偏移量;
* class,structure 和数据的类型定义;
* Frame Pointer Omission 数据,用来在x86上的native堆栈的遍历;
* 源代码文件的名字和行数;
.NET PDB只包含了2部分信息:
* 源代码文件名字和行数;
* 和局部变量的名字;
* 全部的其余的数据都已经包含在了.NET Metadata中了;
函数
三 PDB如何工做工具
当你加载一个模块到进程的地址空间的时候,debugger用2中信息来找到相应的PDB文件。第一个毫无疑问就是文件的名字,若是加载 zzz.dll,debugger则查找zzz.pdb文件。在文件名字相同的状况下debugger还经过嵌入到PDB和binay的GUID来确保 PDB和binay的真正的匹配。 因此即便没有任何的代码修改,昨天的binay和今天的PDB是不能匹配的。可使用dempbin.exe来查看binary的GUID。
在VisualStudio中的modules窗口的symbol file列能够查看PDB的load顺序。第一个搜索的路径是binary所在的路径,若是不在binary所在的路径,则查找binary中hardcode记录的build目录,例如obj\debug\*.pdb, 若是以上两个路径都没有找到PDB,则根据symbol server的设置,在本地的symbol server的cache中查找,若是在本地的symbol server的cache中没有对应的PDB,则最后才到远程的symbol server中查找。经过上面的查找顺序咱们能够看出为何public build和private build的PDB查找不会冲突。
对于private build有时咱们须要在别人的机器上debug的状况,须要将相应的PDB与binary一块儿拷贝,对于加入GAC的.NET的binary,须要将PDB文件拷贝到C:\Windows\assembly\GAC_MSIL\Example\1.0.0.0__682bc775ff82796a相似的binary所在的目录。另外一个变通的方法是定义环境变量DEVPATH,从而代替使用命令GACUTIL将binary放入GAC中。在定义DEVPATH后,只须要将binary和PDB放到DEVPATH的路径,在DEVPATH下的binary至关于在GAC下。使用DEVPATH,首先须要建立目录且对当前build用户有写权限,而后建立环境变量DEVPATH且值为刚才建立的目录,而后在web.config,app.config或machine.config中开启development模式,启动对DEVPATH的使用
<configuration>
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
</configuration> 性能
在你打开了development模式后,若是DEVPATH没有定义或路径不存在的话会致使程序启动时异常"Invalid value for registry"。并且若是在machine.config中开启DEVPATH的使用会影响其余的全部的程序,因此要慎重使用machine.config。
最后开发人员须要知道的是源代码信息是如何存储在PDB文件中的。对于public builds,在运行source indexing tool后,版本控制工具将代码存储到你设置的代码cache中。对于private builds,只是存储了PDB文件的全路径,例如在c:\foo下的源文件mycode.cpp,在pdb文件中存储的路径为c:\foo\mycode.cpp。对于private builds可使用虚拟盘来增长PDB对绝对路径的依赖,例如可使用subst.exe将源代码路径挂载为V:,在别人的机器上debug的时候也挂载V:。
.NET PDB文件究竟是什么?
PDB全称Program Database,不知道中文翻译叫什么。相信使用过VS的人对于这个拓展名的文件不会陌生,这个文件主要会存储对应模块(dll或者exe)内部的全部符号,以及符号对应的地址、文件名和行号。
PDB全称Program Database,不知道中文翻译叫什么。相信使用过VS的人对于这个拓展名的文件不会陌生,这个文件主要会存储对应模块(dll或者exe)内部的全部符号,以及符号对应的地址、文件名和行号。
这个文件会在咱们调试的时候被使用到,这个东西能够理解为调试的时候应用程序和源文件之间的一个桥梁。正是归功于这个文件,咱们才能在debug的时候看到程序当前执行相对应的代码和监视到一些变量。
PDB文件何时产生?
PDB文件是在咱们编译工程的时候产生的,它是和对应的模块(exe或dll)一块儿生成出来的。咱们通常可能不会意识到PDB文件的重要性,由于若是只是咱们本地进行开发,咱们老是可以进行调适。这里我要引入两个概念:Private Build和Public Build。Private Build指的是在开发机器上的编译,Public Build指的是在负责编译的机器上的编译。
正如上面我所说Private Build通常不会有问题,由于在编译出来的机器上进行调试全部必要的文件都在该在的地方。全部大部分不能调试的问题都发生在Public Build的状况下。
若是你的应用程序须要发布或者看成产品卖得,你就须要特别注意要保存你发布出去的那个版本的PDB文件和源文件。注意:你只有一次机会保存着发布出去的PDB文件,若是你弄丢了将没法找回。<固然使用Reflector 相似的工具去调试也是能够的>
为何PDB这么重要?
也许你会认为若是拿一份如出一辙的源代码从新编译一个PDB文件,而后用来调试就好了。我也曾经这么认为过,直到有一天…......
直接的缘由是由于VS生成出来的二进制文件的Header部分里面包含了它对应的PDB的GUID,PDB也包含一个GUIID,这两个GUID实在编译的时候添加进去的。VS调试器在载入PDB的时候会去比对这个两个GUID,若是不一致,那么就不能使用。
固然上面那个缘由只是一个表面现象,根本缘由是既是两份如出一辙的代码编译器编译出来的文件多是不同的。由于编译器在编译的时候会对代码进行优化,而同一份代码可能会有不少种优化的方法,它会根据当时的具体机器的环境等状况选择一个最快的生成方法。因此它生成出来的文件有多是不同的!因此若是连生成出来的文件都不同,那么原来的那个PDB里面的符号对应的地址也就没有意义了。
如何查看二进制文件和PDB的GUID?
使用VS自带的DUMPBIN工具能够查看二进制文件所指望的PDB的GUID。基本用法就是DUMPBIN /HEADER 文件,具体用可可参考MSDN。
查看PDB的GUID能够用下面这个工具,直接将PDB拉进去便可。http://www.codeproject.com/Articles/37456/How-To-Inspect-the-Content-of-a-Program-Database-P
PDB文件的查找策略
先上试验结果,能够再调试的时候从Visual Studio 的Module串口中查找到一个module的symbol的查找策略。从截图中咱们能够看到结果以下:
1. 文件被执行或者被载入的地址
2. 就是硬编码在PE文件头中的那个地址。你们能够看到obj\<config>才是最原始生成的地址,只是以后被拷贝到了第一个地址中去了。
2.5 若是配置了符号服务器,第二步之后应该先去符号服务器的缓存目录下找,若是找不到再去符号服务器上去找。找到的话就会下载到缓存目录。
3. 第三部分是我VS中设置的一些符号查询的目录,由于我装过Reflector因此默认加了这几个目录在个人设置中。
4. Windows文件夹。
这里有一个比较有意思的现象就是,VS的查找策略都是会先找一个目录下的symbol\exe\project.pdb,而后exe\project.pdb,最后才找project.pdb。这个顺序有点出人意料。
PDB文件会影响性能么?
可能有些人会以为PDB文件的生成会对最终的应用程序的性能产生必定的影响,因此以为在发布版中不该该生成PDB文件。
错!对于.NET应用程序来讲,生成PDB文件不会影响编译器的优化,因此也彻底不会影响应用的性能。只会对于生成的程序集中的一个DebuggableAttribute的属性产生影响。有兴趣的人能够阅读Do PDB Files Affect Performance?
小结
由于微软并未公布PDB内部细节,只公开了一些API,因此对于这个文件一直是一个迷。本文只是写了一些我学习到的以及我以为.net程序员有必要知道的一些知识。若是其中有不对之处望指出,之后若是有更深刻了解会另外补充。