正在编译Release和Debug会生成不同的IL代码+不同的机器代码吗?

时间:2012-12-06 20:25:31

标签: c# .net vb.net csc .net-framework-version

我听说在发布模式下编译会生成优化代码而不是调试模式,这很好。

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

感谢

5 个答案:

答案 0 :(得分:14)

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

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

打开了真正的优化器,它是内置于抖动中的优化器。您将在this answer中找到它执行的优化列表。请注意这种方法的有用性,任何语言都可以从抖动而不是编译器中获得代码优化器。

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

答案 1 :(得分:3)

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

我建议您采用一个小示例程序,以两种方式编译它,然后查看ildasm中的输出。

C#编译器不执行很多优化 - JIT编译器完成了大部分工作 - 但我认为存在一些差异。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

免责声明:复制自Hans的回答here

this Microsoft knowledge base article

答案 4 :(得分:0)

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

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

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

因此,如果你这样做,你会得到不同的IL。