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

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

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

谢谢

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

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

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

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

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

我建议你拿一个小样本程序,以两种方式编译它,然后查看ildasm中的输出。

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

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

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

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

请参阅此Microsoft知识库文章 。

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

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

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