在C#中优化代码是否存在风险?

Vre*_*nak 20 .net c# compiler-construction optimization settings

在VS2010 Pro的构建设置面板中,有一个带有"优化代码"标签的CheckBox ......当然,我想检查一下......但是要非常谨慎,我问我的兄弟,并且他说它未经检查以进行调试,并且在C++中它可能会做一些破坏或破坏代码的事情......但他不了解C#.

所以我的问题是,我可以在此框中查看我的发布版本,而不必担心它会破坏我的代码吗?第二,如果它可以破解代码,何时以及为什么?欢迎解释链接.

我正在谈论的CheckBox.

Dav*_*nan 25

您通常会在发布版本中使用此选项.这样做是安全和主流的.没有理由害怕在启用优化的情况下发布代码.启用优化可能会干扰调试,这是禁用调试版本的一个很好的理由.

  • 它并不那么简单.抖动是否将启用优化器主要取决于是否连接了调试器.注意工具+选项,调试,常规,"抑制模块加载时的JIT优化"设置.取消它可以调试优化的代码. (3认同)
  • 它与评估顺序无关.问题是x86 FPU有一堆80位精度的寄存器.优化器使用堆栈来避免将计算结果存储回内存.效率更高但中间结果不会被截断回64位.从而改变计算结果.对于x64抖动不是问题,它使用的是XMM寄存器,而不是64位.当时听起来像个好主意:) (3认同)
  • IIRC有一些边缘条件,当变量删除可能导致浮点计算给出不同的值(由于没有从原始大小强制它) (2认同)

key*_*rdP 16

优化不应该真正破坏您的代码.Eric Lippert 在这里有一篇文章解释了当你打开那面旗子时会发生什么.性能增益因应用程序而异,因此您需要使用项目对其进行测试,以确定是否存在任何明显的差异(在性能方面).


Tud*_*dor 7

在未以其他方式发生的释放模式下运行时,可能会出现一些错误.想到臭名昭着的"非挥发性旗帜":

flag = false;

Thread t = new Thread(
   o =>
   {
        while(!flag)
        {
           // do stuff
        }
   });
t.Start();

// main thread does some work

flag = true;
t.Join(); // will never return in release mode if flag is not volatile
Run Code Online (Sandbox Code Playgroud)

这是因为编译器优化,因为标志变量被线程t的核心缓存,因此它无法看到标志的更新值.

  • 代码被打破,独立于任何编译器标志.即使在调试模式下,这也可能导致问题(就像优化代码中的完美一样).启用优化可以使一些错误更明显吗?当然,但它不会破坏有效的代码. (4认同)
  • 该代码刚刚破解.它偶然在调试中工作.在发布模式下,你的运气就用完了. (2认同)
  • 我认为它正好被打破*因为*它是一个众所周知的编译器/ CPU重新排序/缓存问题.没有理由为什么代码应该返回而不将`flag`更改为volatile或插入`Thread.MemoryBarrier()`.通过调试构建获得幸运意味着隐藏了一个错误,而不是缺失. (2认同)