预编译头

如果你的vc程序中使用了预编译头,并且生成过调试版本。如果有一天你突然发现目录中有个vc100.pdb的莫名其妙的东西而把它删掉了,当你尝试再次生成程序并调试时,你会收到这个错误:

×:\××××××\vc100.pdb 不是创建此预编译头时使用的 pdb 文件,请重新创建预编译头。

现在你知道了了吧,vc100.pdb是创建此预编译头时使用的 pdb 文件,在再次生成调试版本时还是要用到的。

 

----------------------------------------------------------------------------------------

 

为什么需要vc100.pdb这个文件的原因

  连接二进制指令和源代码之间的纽带——符号是如何被编译器生成的呢?要具体了解这个内容我们需要先简单回顾一下微软调试信息格式的历史。

COFF:

  最早的调试信息格式是COFF格式,这种格式内嵌到可执行文件中的,它能记录函数、变量、行号、FPO等信息。

CodeView:

  随后就是比较熟悉的CodeView了。这种调试信息的格式提供了内嵌和分离两种形式,和PDB唯一的不同就是没有编辑并继续的功能。独立的CodeView调试信息存储在.dbg文件中。

PDB:

  而微软最新的调试信息格式就是PDB(Program Data Base)了。这种调试信息和可执行文件是完全分离的。他记录了很多丰富的信息,同时还提供了调试并继续、增量链接的功能。不过这种调试信息的格式并没有官方的公开文档,要操作它一般只有通过debughelp或者DIA。PDB又分为两种格式,一种是vc6使用的PDB2.0,后来的版本则全是PDB7.0。PDB7.0是不能向下兼容的。

编译器产生符号的过程

  我们看到调试信息是逐步发展的,最新的调试信息格式为PDB7.0。这是一种和可执行文件分离的格式。对于可执行文件,一般只有几百字节的额外负担。下面我们仅讨论PDB这种调试信息格式。

  如果指定生成调试信息,编译器在每次编译完文件以后就会产生一个obj文件,然后同时产生它对应的调试信息。当我们进行连接的时候,编译器就会帮我们把所有obj统一编译为一个可执行文件,然后所有的调试信息统一生成一个PDB文件。

  如果我们是生成静态库,那么编译器编译完各个源代码以后会统一产生lib文件,同时也将所有的调试信息生成到一个pdb中。如果我们在编译可执行文件的同时需要使用某一个静态库,那么编译器也需要使用到静态库的调试信息,最终可执行文件和调试信息都被单独地生成。

 

 

编译器选项

  对于VS系列编译器,我们可以有一个总开关:/debug。如果没有这个链接选项,所有调试信息均不会被生成。/pdb可以指定符号文件的名称;/pdbstripped可以指定是否同时产生一个公共符号(public symbol)。

  编译选项则有:/Z7 /Zi /ZI 3种。其中/Z7表示生成CodeView格式的调试信息;/Zi表示生成不支持编辑并继续的PDB调试信息;/ZI表示生成支持编辑并继续的PDB调试信息。

  上面提到的选项均有项目属性的GUI设置与之对应:

 

 

 

 

静态库的符号问题

  曾经遇到过一个问题,就是使用了vc6编译的静态库,然后在vs2008中进行链接。结果每次链接的时候都产生警告,提示没有找到静态库的符号,结果就像没有调试信息一样。这个问题研究很久无果。

  后来自习研究了一下静态库的编译方式才解决了问题。上面已经提到,静态库的PDB是每个文件的调试信息的集合,而默认情况下静态库生成的PDB文件都是VCX0.PDB,例如vs2008就是VC90.PDB,VS2010就是VC100.PDB。生成静态库以后,最终的可执行程序进行链接时候,就会根据lib中各个obj记录的信息区找VCX0.PDB,而这个文件就是我们需要的。如果我们要链接很多个静态库,可能就需要在编译静态库的时候/FD给静态库的符号重命名了。

  这一点在.NET中解决得很好,所有依赖的程序集符号都会被自动保存,并且程序集之间的符号不会合并为一份。

 

  符号的生成非常简单,几个编译选项就搞定,默认情况下DEBUG模式都会产生编辑并继续的符号,而Release模式建议也使用/Zi来产生对应调试信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
预编译(Precompiled Header)是一种优化编译时间的技术。它可以将一些常用的文件预先编译好,然后在编译源文件时直接使用预编译好的文件,从而加快编译速度。 在 Visual Studio 中,预编译相关的属性配置都在“C/C++” -> “预编译”选项卡中。这些属性包括: - 预编译文件(Precompiled Header File):指定预编译文件的名称,默认为“stdafx.h”。 - 预编译生成器(Precompiled Header Output File):指定在生成预编译文件时要使用的 .cpp 文件,默认为项目的主 .cpp 文件。 - 预编译类型(Precompiled Header Mode):指定预编译的生成方式,有“使用”和“创建”两种选项。 - 预编译使用(Use Precompiled Header):指定是否启用预编译功能。 其中,最重要的属性是“预编译文件”,它指定了预编译文件的名称。默认情况下,Visual Studio 会自动生成一个名为“stdafx.h”的预编译文件,并在需要使用的源文件中包含该文件。如果你想使用其他名称的预编译文件,需要手动修改该属性。 另外,预编译生成器和预编译类型也需要根据项目的实际情况进行配置。如果你的项目中只有一个 .cpp 文件,可以将预编译生成器设置为该文件;如果有多个 .cpp 文件,可以选择项目的主 .cpp 文件作为预编译生成器。预编译类型可以根据项目的实际情况选择“使用”或“创建”两种方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值