【问题标题】:Bizarre ternary operator behavior in debugger on x64 platformx64 平台上的调试器中奇怪的三元运算符行为
【发布时间】:2011-10-27 09:31:53
【问题描述】:

我在我的 C# 代码中使用了一个非常简单的三元表达式:

helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();

在这两种情况下,表达式的每个路径上的函数都返回一个非空对象,但是如果我在调试器中查看结果,它是空的,直到我在代码中引用它,例如使用断言:

Debug.Assert(helperClass.SomeData != null);

只有在调试模式下使用“x64”或“任何 CPU”平台设置时才会出现这种情况。在“x86”模式下没问题。

在假设我在编译器或调试器中发现错误之前,我会非常谨慎,但我找不到任何其他解释此行为的原因。

这是一个完整的类来做repro,只需在x64模式下在调试器中调用SomeClass.SomeAction()并逐步查看它:

public class SomeClass {
    public bool HasData;
    public object SomeData;

    private SomeClass() {
        HasData = false;
    }

    public static void SomeAction() {
        var helperClass = new SomeClass();
        // Exhibits weird debugger behavior of having helperClass.SomeData = null after this line:
        helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();

        // Note that trying helperClass.SomeData.ToString() returns a debugger error saying SomeData is null

        // But this code is just fine
        //if(helperClass.HasData) {
        //    helperClass.SomeData = GetSomeData();
        //} 
        //else {
        //    helperClass.SomeData = GetSomeOtherData();
        //}

        // In both cases though, after this line things are fine:
        Debug.Assert(helperClass.SomeData != null);
    }

    private static object GetSomeData() {
        return new object();
    }

    private static object GetSomeOtherData() {
        return new object();
    }
}

是我遗漏了什么还是 x64 调试器中的错误?我正在使用调试模式,因此不应该存在任何优化。

【问题讨论】:

  • 请注意,生成的调试符号生成的优化实际上是正交的。同时打开调试符号和优化是合法的,尽管有些不寻常。可能需要仔细检查您是否处于那种奇怪的配置中。
  • 对于我的活动 (Debug/x64) 配置,未选中“构建”选项卡下的“优化代码”复选框。我应该检查其他地方吗?
  • 不;听起来这不是问题。
  • 刚刚尝试过(关闭优化代码,开启调试)并可以看到所描述的行为 - 在 x86 中,直接在 SomeData != null 行之后,而在 x64 中,它在第一次访问时“变为!= null”(不是来自调试器,而是在代码中)......比较生成的 IL 的样子可能会很有趣......
  • @Jeff:听起来确实是一个错误,但我没有复制它,所以我无法确认。听起来像是在 Connect 上发帖的好人选。我不知道是否已经有一个案例。我注意到多年来有许多奇怪的错误涉及条件运算符的代码生成和调试。用于静态确定堆栈槽的已知类型的精确 CLR 规则可能有点棘手,并且会导致错误。如果这是其中的另一个,我不会感到惊讶,但就像我说的,我没有亲自复制它。

标签: c# visual-studio-2010 ternary-operator


【解决方案1】:

根据 Eric Lippert 的建议,这可能是一个错误,我已为此问题提交了官方 Connect 错误:https://connect.microsoft.com/VisualStudio/feedback/details/684202

感谢大家的反馈!

更新:他们回复我说他们已经在下一版本的编译器中修复了这个极端情况。万岁! :)

【讨论】:

    【解决方案2】:

    对我来说,这似乎不是调试器中的错误,而是编译器中的错误...

    将代码改为

    { helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData(); }
    

    生成的 IL 不同,调试器按预期工作...

    【讨论】:

    • 为什么必须在其周围放置 {}?
    • 我不是说你必须...只是在反汇编该行时 Reflector 给了我一些奇怪的代码后似乎可以工作的东西...
    • 这似乎是一个错误(可能只是在您建议的编译器中)。我正在通过将其转换为 if 语句来解决它,即使 ReSharper 认为我这样做是个白痴:)
    • 不管 ReSharper 在这种情况下说什么...除了 ReSharper 有一些绝妙的想法来解决它 :-)
    猜你喜欢
    • 2013-10-29
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    相关资源
    最近更新 更多