(如何)调试改变程序的工作流程?

考虑以下简单程序:

var dblMax = Double.MaxValue; var result = (dblMax * 1000) / 1800; Console.WriteLine(result); 

当我在调试模式下构建它并运行(Ctrl + F5)或调试(F5)它时,它打印9.987140856842E+307

当我切换到释放模式并运行(Ctrl + F5)时,它会打印8表示无穷大。

我知道这种差异是由于在发布模式下完成的一些编译器优化。

但是,如果我在发布模式下调试(F5) 相同的版本,它会再次打印9.987140856842E+307

我正在调试的事实如何改变计算结果?

编辑:

我不问为什么调试模式和释放模式产生不同的结果。 我想知道为什么发布模式会产生不同的结果,这取决于我是否调试(F5)(Ctrl + F5)。

调试时,JITter的行为不同。

首先,在许多情况下,局部变量的寿命会发生变化,以便可以检查。 在计算过程中使用变量后,请考虑使用断点。 如果JITter知道变量不会在表达式之后使用,并且它没有延长变量的生命周期,那么最终可能无法查看该变量,这是调试的核心function。

JITer非常清楚知道变量何时仍然有用。 如果在此期间寄存器可用,则可能最终使用该寄存器来存储变量。

但是,如果附加了调试器,它可能会决定使用内存位置,因为生命周期已经改变,因此代码的那部分没有可用的寄存器。

CPU的浮点寄存器比相应的浮点存储格式具有更高的精度,这意味着一旦您将值从寄存器中提取到内存中,或者只是将其一直存储在内存中,您将体验到较低的精度。

RELEASE和DEBUG构建之间的区别可能会最终决定这些事情,调试器的存在也是如此。

此外,不同的.NET运行时版本之间可能存在差异,这可能会影响这一点。


正确编写浮点代码需要深入了解您尝试做什么以及机器和平台的各个部分将如何干扰。 我会尽量避免编写这样的代码。

这与浮点精度严格相关。 在调试模式下,编译器使用80位精度。 在发布模式下,编译器使用64位截断结果。

当这种情况发生或不发生时,取决于几个配置,设置和环境变量。 例如,您可以对发布模式的配置进行优化。 这应该有所帮助。

看看这个Jon Skeet的回答: https : //stackoverflow.com/a/18417944/637840

看看这个:

 var result1 = (dblMax / 1800) * 1000; // 64-bit precission is needed var result2 = (dblMax * 1000) / 1800; // 80-bit precission is needed Console.WriteLine(result1); Console.WriteLine(result2); 

这只是确认上述答案的例子。