C# - .NET中是否真的需要调试版本

4
如果发布版本生成.pdb文件,您可以进入每一行,设置断点等,那么为什么还要构建我的组件的“调试”版本呢?
我在我的项目中使用C#,没有问题调试发布版本。在C++中,我在调试优化代码时遇到了问题,但在C#中它能正常工作。我不是在谈论像if(false)这样愚蠢的代码块...
8个回答

8
发布版本更加优化,例如,在我调试发布版本时,如果局部变量的值不会被运行时使用,它们的值就会消失,这让我很烦恼。

7

一个原因是附加 vs. 启动。

如果在 .Net 中启动零售进程,则调试几乎与启动调试进程一样好。您可能不会注意到任何调试经验上的区别。

附加是完全不同的游戏。C# 和 VB 都通过 /optimize+ 标志传递给零售版本。这将在程序集级别嵌入 DebuggableAttribute,而没有 DebuggingMode.DisableOptimizations 标志。在进程启动期间,VS/CLR 将通信以基本忽略此事,并禁用影响调试的 JIT 优化。在附加期间,没有这样的项目发生,JIT/CLR 将进行最优化。我保证,在这种情况下,调试体验要差得多。

您可以在 VS 中进行实验

  • 切换构建为 Release
  • 使用 CTRL+F5 进行无调试启动
  • 附加到进程。

你是不是指的是“发布”而不是“零售”...? - Matt

5
在(c#) winforms中,您不能在发布版本中进行编辑和继续。

3
除了其他答案,我使用自动生成的#define DEBUG来在未捕获异常时改变行为:
  • 如果运行在发布模式下,则向用户显示一个漂亮的消息并可选择记录错误日志。
  • 如果运行在调试模式下,则不做任何处理(这将导致调试器中断)。

2
有几个原因:
  • 默认情况下,发布版本在 PDB 文件中不包含太多调试信息。我认为这个选项曾经更加突出 - 现在它在“输出”下的“高级设置”中,可能的值为“none”、“full”(用于调试版本的默认值)和“pdb-only”(用于发布版本的默认值)。
  • 默认情况下,发布版本是经过优化的:虽然这在 C# 中的影响远不及其他语言(例如 C++),因为 JIT 完成了大部分工作,但可能会有一些差异,使得调试发布版本更加困难。
  • 默认情况下,发布版本不定义 DEBUG 符号,因此任何对 Debug.Assert 等的调用都将被删除。
当然,很多这些内容可以在构建配置中进行更改。一个相当常见的方法是保持默认设置不变,除了在发布版本中包含更多的调试信息,这可以给你提供更有用的堆栈跟踪(如果你使用调试器,也可以提供更好的调试体验)。

我认为你在第一点上是错误的。PDB文件已经包含在VS的默认配置中,适用于发布版本(通过控制台应用程序进行验证)。否则,在调试期间无法提供本地信息。 - JaredPar
现在你让我很好奇。我不知道完整版与仅PDB会对我们的PDB生成过程产生什么影响。我认为通常包含的任何项目都不能被排除在PDB之外。希望我晚些时候有时间去尝试一下。 - JaredPar
@Jon,我相信其中至少一部分的区别在于存在的DebuggerNonUser代码和CompilerGenerated属性的数量。可能还有其他一些。 - JaredPar
这不是指 pdb 文件而是汇编文件的大小差异吗? - Jon Skeet
@Jon 嗯,我想说它也会影响 PDB 大小,但原因现在逃脱了我的记忆。 - JaredPar
显示剩余8条评论

0

发布版本比调试版本进行了额外的优化,但是调试版本也会略微改变GC的行为,以确保您在调试会话中不会因对象被收集而出现错误。调试版本还会阻止某些JIT优化的发生,这将对您的调试会话产生负面影响。


这不是JIT编译器的特性而不是GC吗? - Brian Rasmussen

0

我同意Lennaert的观点 - 我倾向于在不同的构建版本中进行不同的错误处理。例如,对于某些应用程序,在调试构建中我会非常严格。预先和后置条件、断言、异常等等。基本上,我试图强制开发人员正确使用我的库。另一方面,在发布版本中,我会放松这些条件以提高性能。


0
当你使用"按设计契约编程"时,重要的是要有两个版本的构建——发布版不检查前置条件、后置条件和类不变量,而调试版通过断言来检查它们。
在某些情况下,前置条件检查可能会在发布模式下保持活动状态(搜索相关问题),但这并不改变整个故事。
在开发阶段,您检查所有契约假设,当您发布时,您不再检查它们——您知道您已经测试了代码并且它可以工作,所以您只是依赖于您之前的假设——这也是它们最初的目的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接