c# - 即使条件评估为 false,If 语句似乎也在评估

标签 c# .net assembly x86 .net-assembly

昨晚工作到很晚,我们试图弄清楚为什么会出现故障。验证检查在不应该的时候失败了。

我们最终向这段代码添加了一条打印语句(从 Reflector 反汇编以检查代码是否确实是我们编写的内容):

public static string Redacted(string name, DateTime lastModified)
{
    long ticks = lastModified.Ticks;
    if ((ticks != (ticks - (ticks % 10000L))) &&
            (lastModified != DateTime.MaxValue))
    {
        Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
            lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
            ticks, ticks - (ticks % 10000L)));

它打印(重新格式化):

Last Modified Date = '22/03/2011 12:16:22.000'.
Ticks     = '634363497820000000'.
TicksCalc = '634363497820000000'            

但条件是“ticks”(等于上面打印的 Ticks)不等于“(ticks - (ticks % 10000))”(等于 TicksCalc)! 634363497820000000 != 634363497820000000?!

为了确定这里发生了什么,我们添加了另外两条语句:

long ticks = lastModified.Ticks;
/* Added following two lines: */
long num2 = ticks - (ticks % 10000L);
Log.Debug((ticks == num2).ToString());
/* */
if ((ticks != (ticks - (ticks % 10000L))) &&
        (lastModified != DateTime.MaxValue))
{
    Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
        lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
        ticks, ticks - (ticks % 10000L)));

正如它应该有的那样,这个打印了 true(当使用相同的值进行测试时),并且没有写第二行。

感觉有点迷茫,然后我们再次删除了这两行,重新编译并重新运行。原来的行为会自己重复。

今天早上,I recorded a video .

该视频首先展示了使用“损坏”代码在方法中遇到断点,然后使用“工作”代码重建并重新运行。请注意,即使调试器显示 if 条件的计算结果为 false,主体仍会被输入。

我以前在调试器观察时看到过类似的事情发生,因为调试器强制对某些事情进行评估,但无论是否使用调试器都会发生这种情况。

此外,这只发生在 Release模式下(即启用 JIT 优化)。

两个版本的反汇编方法如下:working , not working .我真的无法阅读汇编,所以我将它们张贴在这里以期得到解释。

我希望答案不是我完全忽略的显而易见的东西......!

编辑:这是 IL。我不认为它有什么问题,因为它反编译为正确的 C#:

更新:

Confirmed as a bug by Microsoft, to be fixed in the next release .

最佳答案

我尝试了一些简化的代码: http://nopaste.info/2c99a0e028_nl.html

最有趣的变化是:

static readonly long variableZero=0; 
const long constZero=0; 

public static void Broken2( long ticks2) 
 { 
     long ticks = ticks2+variableZero; 
     if (ticks != (ticks - (ticks % 10000L))) 
     { 
         string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'", 
             "n/A", 
             ticks, ticks - (ticks % 10000L)).Dump(); 
     } 
 }

如果我将 variableZero 替换为 constantZero,它就可以工作。


所以我很确定这是抖动或编译器错误。

我已在 MS Connect 上提交错误报告: https://connect.microsoft.com/VisualStudio/feedback/details/671105/jitter-or-c-compiler-bug#details


更新:只有在没有附加调试器的情况下才会出现奇怪的行为。即启用 Jit 优化时。所以我很确定这是一个抖动错误。

对于没有 linq-pad 的人,现在有一个普通的 C# 控制台项目:http://nopaste.info/00a0e37328_nl.html

关于c# - 即使条件评估为 false,If 语句似乎也在评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6054987/

相关文章:

.NET 通过 AppSetting 通过指纹查找证书

.net - 如何删除WPF中折线图周围的边框?

assembly - 在内存位置调用 `add` 是否比在寄存器上调用它然后移动值更快?

c++ - 存储只读数据混合程序集和 C++

assembly - 使用bx寄存器保存索引可以吗?

C# 文本冒险音乐问题

c# - System.ObjectDisposedException : The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

c# - MailChimp MCAPI.NET - 订阅分组

c# - 列字符串格式

c# - 从 SqlDataReader 检索 INSERT 语句的基础异常