9

我听说在 Release 模式下编译会比在 Debug 模式下生成优化的代码,这很好。

但这是 IL 中的优化吗?一旦CLR运行它,它就在机器代码中吗?Release和Debug中编译的元数据结构与PE不同吗?

谢谢

4

5 回答 5

14

Build in Release build 打开 C# 编译器的 /optimize 编译选项。这有一些副作用,IL 确实发生了变化,但变化不大。值得注意的是,编译器不再努力使代码完全可调试。例如,它会跳过一个空的静态构造函数,它不再发出允许您在花括号上设置断点并允许具有不同范围的局部变量在堆栈帧中重叠的 NOP 操作码。小东西。

最重要的区别是为程序集发出的 [Debuggable] 属性,其 IsJITOptimizerDisabled 属性为 false。

这会打开真正的优化器,即抖动中内置的优化器。您将在此答案中找到它执行的优化列表。请注意这种方法的有用性,任何语言都受益于在抖动中使用代码优化器而不是编译器。

所以简而言之,IL 的变化非常小,生成的机器代码变化非常大。

于 2012-12-06T20:41:36.950 回答
3

是的,IL 中有一些优化——特别是调试版本将包含 NOP 指令,我相信这使得调试器可以轻松插入断点。在提供的调试信息级别(行号等)方面也存在潜在差异。

我建议你拿一个小示例程序,以两种方式编译它,然后查看ildasm.

C# 编译器没有做太多优化——JIT 编译器做了大部分优化——但我认为存在一些差异。

于 2012-12-06T20:27:58.817 回答
1

cil 不同,它是优化的。由于机器代码是 cil 的翻译,因此它也有所不同。可以自己看,在visual studio中打开反汇编窗口即可。元数据应保持不变,因为您不会更改版本之间的类合同结构。

于 2012-12-06T20:29:17.187 回答
0

在 VB 中有一个副作用是编辑 + 继续支持编译到可执行文件中,这可能会导致内存泄漏。它受到使用 WithEvents 关键字声明的任何事件的影响。WeakReference 跟踪这些事件实例。问题是,如果您在没有调试器的情况下运行应用程序,这些 WeakReferences 就会泄露。进程消耗内存的速率很大程度上取决于创建了多少类实例。泄漏是每个对象每个事件 16 个字节。

免责声明:从汉斯的回答复制here

请参阅此 Microsoft 知识库文章

于 2012-12-06T22:02:17.877 回答
0

这不是确切问题的答案。只是要补充一点,您可以在预处理器标记的帮助下有目的地标记哪些代码必须在调试模式下运行,哪些在发布模式下运行。

 #if DEBUG
    // code only meant for debug mode
 #endif

 #if NOT DEBUG
    // code only meant for release mode
 #endif

所以如果你这样做,你会得到不同的 IL 生成。

于 2013-10-14T07:04:48.403 回答