释放生成的.pdb文件,为什么?


264

为什么.pdb在发行版中进行编译时Visual Studio 2005会生成文件?我不会调试发布版本,为什么会生成它们?


18
为什么要重新生成pdb?因此,当崩溃报告从头开始时,您就有调试它的信息。另一个价值是客户可以在原始作者不进行调试的情况下对其进行调试。
伊恩·博伊德

@IanBoyd:该评论的第二句话暗示您部​​署了PDB。在绝大多数情况下,这是不可取的。
IInspectable

3
@IInspectable还是可取
Ian Boyd

@IanBoyd:绝大多数情况不包括OS部署。此外,这些PDB不包含私有符号,当您生成PDB时,默认情况下会包含这些私有符号。
IInspectable'6

@IInspectable另一方面,释放PBD 可取的。理想情况下,是的,每个人都将编写编译为IL的代码,以便我们自己获取符号信息。但是本机代码编译器仍然没有简便的方法来支持现场调试。
伊恩·博伊德

Answers:


416

因为没有PDB文件,将无法通过地址级调试来调试“发布”版本。优化确实会对代码产生影响,因此如果出现问题(例如引发异常),很难找到罪魁祸首。甚至设置断点也非常困难,因为源代码行无法与生成的汇编代码一一对应(甚至顺序相同)。PDB文件可以帮助您和调试器,使事后调试变得更加容易。

您指出,如果您的软件已准备好发布,则应该在那时完成所有调试。尽管这确实是正确的,但有几点要牢记:

  1. 应该使用“发布”版本来测试和调试应用程序(在发布之前)。这是因为打开优化功能(默认情况下在“调试”配置下将其禁用)可能会导致出现一些细微的错误,而这些错误是您以前无法捕捉到的。在进行调试时,您将需要PDB符号。

  2. 客户经常报告仅在“理想”条件下出现的边缘情况和错误。这些都是在实验室中几乎不可能复制的东西,因为它们依赖于该用户计算机的某些古怪配置。如果他们对客户特别有帮助,他们将报告抛出的异常并为您提供堆栈跟踪。否则他们甚至会让您借用他们的机器来远程调试软件。在任何一种情况下,您都希望PDB文件为您提供帮助。

  3. 始终在启用优化的“发布”版本上进行性能分析。再一次,PDB文件将派上用场,因为它们允许将正在分析的汇编指令映射回您实际编写的源代码。

编译,您将无法返回并生成PDB文件。*如果您在构建期间未创建它们,那么您将失去机会。创建它们没有任何伤害。如果您不想分发它们,则只需从二进制文件中忽略它们即可。但是,如果您以后决定要它们,那您就不走运了。最好始终生成它们并存档副本,以防万一您需要它们。

如果您确实要关闭它们,则始终可以选择。在项目的“属性”窗口中,将要更改的任何配置的“调试信息”选项设置为“无”。

请注意,但是,“调试”和“发布”配置默认情况下确实使用不同的设置来发出调试信息。您将要保留此设置。对于调试版本,“调试信息”选项设置为“完整”,这意味着除PDB文件外,调试符号信息也嵌入到程序集中。您还将获得支持酷炫功能(例如编辑并继续)的符号。在发布模式下,选择了“仅pdb”选项,听起来好像只包含PDB文件,而不会影响程序集的内容。因此,这并不像目录中仅存在或不存在PDB文件那样简单/bin。但是假设您使用“仅pdb”选项,则PDB文件“

*正如Marc Sherman在评论中指出的那样,只要您的源代码没有更改(或者您可以从版本控制系统中检索原始代码),您就可以重建它并生成匹配的PDB文件。至少,通常。这在大多数情况下都能正常工作,但是不能保证编译器每次编译相同的代码时都会生成相同的二进制文件,因此可能会有细微的差异。更糟糕的是,如果您同时对工具链进行了任何升级(例如为Visual Studio应用Service Pack),则PDB匹配的可能性甚至更低。保证事后可靠的产生在PDB文件中,您不仅需要存档版本控制系统中的源代码,还需要存档整个构建工具链的二进制文件,以确保可以精确地重新创建构建环境的配置。不用说,简单地创建和归档PDB文件要容易得多。


19
“编译后无法生成PDB文件。” -如果您的源代码没有更改,那么您可以在事实发生之后进行重建以生成可用的PDB。默认情况下,windbg不会加载此PDB,但是您可以通过指定/ i选项来强制其加载,例如this .reload /i foo.dll。即使释放foo.dll之后创建了foo.pdb,也将加载foo.pdb。
马克·谢尔曼

我注意到,每个新编译都有不同的哈希摘要,因此即使在相同的环境中,每个版本也存在细微的差异。PDB的地址可能不会随变化而变化,因此需要使PDB脱离该版本吗?只是将其作为一个想法,因为我并不真正了解PDB的工作方式或散列为何会在构建之间改变。
thebunnyrules

1
@the在脚注中,我链接到一篇文章,解释为“根据设计,C#编译器永远不会两次生成相同的二进制文件。C#编译器在每次运行时都在每个程序集中嵌入一个新生成的GUID,从而确保没有两个程序集一点一点相同。” 这就解释了为什么它具有不同的哈希值,因此也具有不同的PDB文件的原因。这可以用十六进制编辑器修复,但不是用户友好的。而且不在此答案的范围之内。
科迪·格雷

3
Roslyn中有一个称为确定性构建的新功能。“ / deterministic标志使编译器在给出相同的输入时发出完全相同的EXE / DLL(逐字节)。” 这意味着最初使用此标志编译的项目,只要您要编译的代码相同,就可以重新编译为完全相同的二进制文件。可以在这里找到更详细的解释确定性构建罗斯林
ķ史密斯

92

PDB可以被生成Release,以及用于Debug。设置为(在VS2010中,但在VS2005中必须类似):

项目→属性→构建→高级→调试信息

只需将其更改为即可None


2
但是,为什么要这样做呢?如果您的软件已准备好发布,那么您应该在那时完成所有调试
m.edmondson 2011年

4
因为您可以调试生产问题。一旦我们必须这样做。
Aliostad

21
将PDB用作生产代码的优点是.NET抛出异常时将使用这些文件。它生成带有文件名和行号的堆栈跟踪,这通常非常方便!
史蒂芬

6
@ m.edmondson:是的,这是正确的。你仍然被告知什么抛出的异常(像FileNotFoundException),但你不会看到一个堆栈跟踪。这使得很难准确地确定哪一代码导致引发异常。
科迪·格雷

2
@ m.edmondson只需添加一下,如果您正在寻找一种工具来远程调试生产环境中的问题,那么Windows SDK附带了一个非常著名的工具WinDbg,该工具支持远程调试。请查看下面提到的链接。希望这可以帮助!msdn.microsoft.com/en-in/library/windows/hardware/…–
RBT

8

没有.pdb文件,实际上不可能单步执行生产代码。您必须依靠其他昂贵且费时的工具。我知道您可以使用例如跟踪或windbg,但这实际上取决于您要实现的目标。在某些情况下,您只想使用生产数据逐步观察远程代码(没有错误或异常),以观察特定的行为,这就是.pdb文件很方便的地方。没有他们,就无法在该代码上运行调试器。


7

为什么要确定不调试发行版?有时(希望很少,但确实会发生),您可能会由于某种原因(时间不同,行为不同或其他原因)从客户那里获得无法在调试版本中重现的缺陷报告。如果该问题在发行版本中似乎是可重现的,那么您将很高兴拥有匹配的pdb。


5
@ m.edmondson使用RDP,Webex等访问远程计算机,然后在其中安装windbg。设置您的符号路径和bam,您真棒!
马克·谢尔曼

链接到更详细的指南会更有帮助。这一单行方法可能会导致人们(例如我自己)走错路。例如,大多数.NET开发人员对Windbg一无所知。
nuzzolilo 2014年

1
@ m.edmondson-Visual Studio的某些版本可以执行远程调试。从调试菜单中,您可以“附加到进程”在远程计算机上。
马修

远程调试生产应用程序实例是一个好主意吗?它不会中断线程的并行执行并在调试时强制它们以串行方式运行吗?
卡夫·哈贾里

4

另外,您可以利用故障转储来调试软件。客户将其发送给您,然后您就可以使用它来标识源的确切版本,并且Visual Studio甚至会使用故障转储提取正确的调试符号集(如果设置正确,还可以获取源)。请参阅有关符号存储的 Microsoft 文档


2

.PDB文件是“程序数据库”的简称。它包含有关调试器调试点的信息以及所使用或参考的资源。当我们将其构建为调试模式时生成。它允许应用程序在运行时进行调试。

在调试模式下,.PDB文件的大小增加。在测试应用程序时使用它。

pdb文件的好文章。

http://www.codeproject.com/Articles/37456/How-To-Inspect-the-Content-of-a-Program-Database-P


1
“在发布或部署时不需要此文件”,除非有人在该发行版本中遇到崩溃,并且从他们那里获得的崩溃报告不包含可用的堆栈跟踪...那么您希望在之后添加它所有。
Nyerguds

不对。没有.pdb文件,您将获得完整的stacktrace,但没有源文件名。收到崩溃报告后,您可以在内部对其进行恢复。如果您在乎自己的知识产权并混淆了来源,则必须保存.pdb文件,而不必进行部署。
TOP KEK

1

在多项目解决方案中,您通常希望拥有一种配置,该配置完全不生成PDB或XML文件。我认为不要将Debug Info每个项目的属性都更改为none,而是添加一个仅在特定配置中起作用的构建后事件会更方便。

不幸的是,Visual Studio不允许您为不同的配置指定不同的生成后事件。因此,我决定通过编辑csproj启动项目的文件并添加以下内容(而不是任何现有PostBuildEvent标签)来手动执行此操作:

  <PropertyGroup Condition="'$(Configuration)' == 'Publish'">
    <PostBuildEvent>
        del *.pdb
        del *.xml
    </PostBuildEvent>
  </PropertyGroup>

不幸的是,这将使构建后事件文本框为空白,并且将任何内容放入其中都可能产生不可预测的结果。


4
这将删除所有*.xml文件,请谨慎操作。
Mariusz Jamro

0

调试符号(.pdb)和XML doc( .xml)文件占总大小的很大一部分,因此不应成为常规部署程序包的一部分。但是,如果需要它们,应该可以访问它们。

一种可能的方法:在TFS构建过程结束时,将它们移至单独的工件。


-1

实际上,如果没有PDB文件和符号信息,就不可能创建成功的崩溃报告(内存转储文件),并且Microsoft不会完全了解导致问题的原因。

因此,拥有PDB可以改善崩溃报告。


但是,如果没有.pdb文件,将会丢失什么呢?
上周

编译后无法生成PDB文件。因此,应该已经在Microsoft保存了软件major.minor [.build [.revision]]的每个版本,以便正确了解发生了什么,但这还不是全部。
prosti

不能保证每次您编译相同的代码时,编译器都会生成相同的二进制文件。
prosti

问题是崩溃报告中将缺少什么以及崩溃报告将如何受到影响。.NET pdb文件仅包含私有变量名称和源文件名称。其他所有内容(方法名称,签名等)都将在来自元数据信息的stacktrace中。
周末时间:

没有PDB文件还包含非私有数据:github.com/microsoft/microsoft-pdb
prosti,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.