我应该将调试信息编译为“完整”或“仅pdb”的发行版吗?


114

在Visual Studio 2010中的C#项目中,如果转到“项目属性”>“生成”>“高级”>“调试信息”,则有三个选项:无,完整或仅pdb。基于对这个问题的回答,我相信我理解完全和仅pdb之间的一些区别。但是,哪个版本更适合发布版本?如果我使用“ full”,将会对性能产生影响吗?如果我使用“仅pdb”,则调试生产问题会更困难吗?

“ full”和“ pdbonly”之间有什么区别?https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/compiler-options/debug-compiler-option


仅pdb或无pdb,始终用于发行版。
嬉皮2011年

13
@leppie谢谢,但我正在寻找该职位的正当理由。
RationalGeek


如果不影响性能,那就太好了。内存影响如何?如果我创建StackTrace实例并请求文件信息,则它必须来自pdb符号数据。是否在应用程序启动时将所有符号加载到内存中?这个大概的内存使用是什么?(例如,相对于代码大小的百分比开销。)
yoyo 2015年

Answers:


90

我会用pdb-only。您将无法将调试器附加到已发布的产品上,但是如果遇到故障转储,则可以在崩溃时使用Visual Studio或WinDBG来检查堆栈跟踪和内存转储。

如果使用full而不是pdb-only,则将获得相同的好处,只是可执行文件可以直接附加到调试器。对于您的产品和客户,您需要确定这是否合理。

确保将PDB文件保存在某个位置,以便在崩溃报告出现时可以引用它们。如果可以设置符号服务器来存储那些调试符号,那就更好了。

如果您选择使用构建none,则当现场发生崩溃时,您将无权追索。您将无法对崩溃进行事后检查,这可能会严重影响您查找问题的能力。

关于性能的说明:

无论约翰·罗宾斯埃里克利珀写了博客文章有关/debug的标志,他们都表明,这个设置为零性能的影响。有一个单独的/optimize标志,指示编译器是否应执行优化。


7
@ Matt,/ debug开关上MSDN文章明确警告使用“完全”设置会对性能产生影响:If you use /debug:full, be aware that there is some impact on the speed and size of JIT optimized code and a small impact on code quality with /debug:full. We recommend /debug:pdbonly or no PDB for generating release code.
Allon Guralnek 2012年

3
@Matt:如果“完全”与“仅pdb”相比没有缺点,而只有优点,为什么“仅pdb”甚至存在?是否有理由在“满”时使用它?另外,您应该在“社区内容”部分的MSDN文章中添加更正。
Allon Guralnek'2

9
链接的约翰·罗宾斯文章中的@AllonGuralnek引用:真正的原因:历史。在.NET 1.0中,存在差异,但在.NET 2.0中没有差异。看起来.NET 4.0将遵循相同的模式。与CLR调试小组仔细检查后,没有任何区别。
bentayloruk

5
这不是真的 您可以仅使用pdb进行构建,并且仍然附加调试器。我只是为了确定。
2015年

2
“我将仅使用pdb进行构建。您将无法在已发布的产品上附加调试器。”您在这里的信息来源是什么?正如@Mark和我都指出的那样,这似乎是不正确的。
MEMark 2015年

66

警告 / debug开关的 MSDN 文档(在Visual Studio中为“调试信息”)似乎已过期!这是它有什么不正确

如果使用/调试:,要知道,没有对速度和JIT优化代码的大小和与/调试代码质量的影响不大一定的影响:。我们建议/ debug:pdbonly或不使用PDB来生成发行代码。

/ debug:pdbonly和/ debug:full之间的区别是,使用/ debug:full时,编译器会发出一个DebuggableAttribute,用于告诉JIT编译器调试信息可用。

那现在是真的

  1. 仅Pdb –在.NET 2.0之前,它有助于调查已发布产品(客户计算机)的故障转储。但这并不允许附加调试器。.NET 2.0并非如此。它与Full 完全相同
  2. 完整 –这有助于我们调查崩溃转储,还允许我们附加调试器以发布构建。但是与MSDN所提到的不同,它不会影响性能(自.NET 2.0起)。它与仅Pdb完全相同。

如果它们完全相同,为什么我们有这些选择?John Robbins(Windows调试之神)发现这些是出于历史原因。

在.NET 1.0中,存在差异,但在.NET 2.0中没有差异。看起来.NET 4.0将遵循相同的模式。与CLR调试团队仔细检查后,完全没有区别。

控制JITter是否执行调试构建的是/ optimize开关。<...>

最重要的是,您要使用/ optimize +和任何/ debug开关来构建发行版本,以便可以使用源代码进行调试。

然后他继续证明这一点。

现在,优化是一个单独开关的一部分/optimize(在Visual Studio中称为Optimize code)。

简而言之,无论DebugInfo设置为pdb-only还是full,我们都将得到相同的结果。建议避免使用“ 无”,因为它会使您无法分析已发布产品或附加调试器的故障转储。


3
很棒的答案!我自己的调查(比较生成的文件)显示了相同的结果。
MEMark 2015年

@rpattabi您能否指定pdbonly和full相同的引用?现在是2019年,文档仍然表明它们不同,并且完整版本将会降低性能。VS2019创建的项目的Release配置调试类型默认设置为pdbonly

@joe MSDN文档msdn.microsoft.com/zh-cn/library/8cw0bt21.aspx的底部有一个讨论。看一看。一位贡献者指出了github.com/dotnet/roslyn/blob/master/docs/compilers/CSharp/…以获得最新信息,其中提到了pdbonly和full。(仅供参考。我不再使用Windows或VS。所以我没有关注那里发生的事情。但是,当我回顾时,我的答案中的信息仍然相关,并且MSDN文档仍然不正确。)
rpattabi

16

您只需要PDB,但不想将PDB文件提供给用户。不过,让它们自己与二进制文件一起使用,使您能够将故障转储加载到WinDbg之类的调试器中,并查看程序实际在哪里失败。当您的代码在您无权访问的计算机上崩溃时,这可能会非常有用。

完全调试将[Debuggable]属性添加到您的代码中。这对速度有巨大影响。例如,某些循环优化可能被禁用,以使单步操作更容易。此外,由于它启用了跟踪,因此它对JIT流程的影响很小。


说得通。无论如何,我并没有真正将DLL分发给用户-这是一个ASP.NET应用程序。但是,您是否可以增强答案并说明为什么应该使用“仅pdb”与“完整”?这是性能问题吗?
RationalGeek

@jkohlhepp:我想补充一点,尽管调试版本的构建有些棘手,因为您会丢失一些信息(由于JIT)。几乎总是,您将看不到方法参数的值。要解决此问题,您可以使用this暂时禁用JIT优化。
Ilian Pinzon

感谢blowdart,并感谢Ilian Pinzon提供的其他信息。我知道您无法使用发行版代码进行完美的调试,但是拥有PDB总比没有好。
RationalGeek

使用“满”设置并不会影响性能。它只是允许将调试器附加到正在运行的进程。
马特·迪拉德

1
有关MSDN Matt的好问题,msdn.microsoft.com / en-us / library / 8cw0bt21,我自己等待答案。
路加·赫顿

4

我正在编写一个未处理的异常处理程序,并且堆栈跟踪包括使用pdb-only时的行号,否则当我选择None时,我只会得到Sub / Function的名称。

如果我不分发.pdb,即使使用仅pdb版本,也不会在堆栈跟踪中获得行号。

因此,我正在分发(XCOPY部署在LAN上)pdb和来自VB应用程序的exe。

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.