C# x64平台上调试器中奇怪的三元运算符行为
我在C代码中使用了一个非常简单的三元表达式: 在这两种情况下,表达式的每个路径上的函数都返回一个非null对象,但如果我在调试器中查看结果,它将为null,直到我在代码中引用它,例如使用断言:C# x64平台上调试器中奇怪的三元运算符行为,c#,visual-studio-2010,ternary-operator,C#,Visual Studio 2010,Ternary Operator,我在C代码中使用了一个非常简单的三元表达式: 在这两种情况下,表达式的每个路径上的函数都返回一个非null对象,但如果我在调试器中查看结果,它将为null,直到我在代码中引用它,例如使用断言: Debug.Assert(helperClass.SomeData != null); 只有在调试模式下使用“x64”或“任意CPU”平台设置时,才会出现这种情况。在“x86”模式下可以 在假设我在编译器或调试器中发现了错误之前,我会非常谨慎,但我找不到任何其他解释来解释这种行为 这里有一个完整的类来执
Debug.Assert(helperClass.SomeData != null);
只有在调试模式下使用“x64”或“任意CPU”平台设置时,才会出现这种情况。在“x86”模式下可以
在假设我在编译器或调试器中发现了错误之前,我会非常谨慎,但我找不到任何其他解释来解释这种行为
这里有一个完整的类来执行复制,只需在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调试器中的一个错误?我正在使用调试模式,因此不应存在任何优化。对我来说,这似乎不是调试器中的错误,但可能是编译器的错误 将代码更改为
{ helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData(); }
生成的IL不同,调试器按预期工作…根据Eric Lippert的建议,这可能是一个bug,我已经针对这个问题提交了一个官方Connect bug: 谢谢大家的反馈
更新:他们回复我说他们已经在下一版本的编译器中修复了这个死角。万岁!:) 请注意,生成的调试符号和生成的优化实际上是正交的。同时启用调试符号和优化是合法的,尽管有些不寻常。可能需要再次检查您是否处于这种奇怪的配置中。对于我的活动(调试/x64)配置,“生成”选项卡下的“优化代码”复选框未选中。我应该去别的地方看看吗;听起来这不是问题所在。只需尝试一下(关闭优化代码,打开调试),就可以看到所描述的行为-在x86中,直接在SomeData一行之后null,而在x64中,第一次访问时它“变为!=null”(不是从调试器而是在代码中)。。。比较一下生成的IL看起来会很有趣…@杰夫:听起来确实像是一个bug,但我没有复制它,所以我无法确认。听起来很适合在Connect上发布。我不知道是否已经有案例了。我注意到,多年来出现了一些奇怪的bug,涉及到条件运算符的代码生成和调试;静态确定已知堆栈槽类型的精确CLR规则可能有点棘手,这会导致错误。如果这是另一个,我也不会感到惊讶,但就像我说的,我个人并没有责备它。你为什么要把{}放在它周围呢?我不是说你必须。。。当Reflector在反汇编这行代码时给了我一些奇怪的代码,这似乎是一个bug(也许正如你所建议的,只是在编译器中)。我通过将其转换为if语句来解决它,即使ReSharper认为我这样做是个白痴:)不管ReSharper在这种情况下说什么。。。除了ReSharper有一些绝妙的想法来解决它:-)
{ helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData(); }