【发布时间】:2014-03-21 18:09:00
【问题描述】:
我一直在寻找您的一些代码不起作用。除了以下行,一切看起来都很好。
Transport = Transport?? MockITransportUtil.GetMock(true);
在执行该行之前,Transport 为空。我看到 GetMock 已执行并且它返回一个非空对象。在该行之后 Transport 仍然为空;
我查看了生成的 IL,我觉得它看起来不错。
IL_0002: ldarg.0
IL_0003: ldfld class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Messaging.TestIGuaranteedSubscriptionBase::Transport
IL_0008: dup
IL_0009: brtrue.s IL_0012
IL_000b: pop
IL_000c: ldc.i4.1
IL_000d: call class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Mocking.MockITransportUtil::GetMock(bool)
IL_0012: stfld class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Messaging.TestIGuaranteedSubscriptionBase::Transport
我们看到函数被调用,stfld 应该获取返回值并设置字段。
然后我查看了程序集,我看到调用已完成,但看起来 RAX 中的返回被下一次调用吹走并且丢失了。
Transport = Transport?? MockITransportUtil.GetMock(true);
000007FE9236F776 mov rax,qword ptr [rbp+0B0h]
000007FE9236F77D mov rax,qword ptr [rax+20h]
000007FE9236F781 mov qword ptr [rbp+20h],rax
000007FE9236F785 mov rcx,qword ptr [rbp+20h]
000007FE9236F789 mov rax,qword ptr [rbp+0B0h]
000007FE9236F790 mov qword ptr [rbp+28h],rax
000007FE9236F794 test rcx,rcx
000007FE9236F797 jne 000007FE9236F7AC
000007FE9236F799 mov cl,1
000007FE9236F79B call 000007FE92290608
//var x = ReferenceEquals(null, Transport) ? MockITransportUtil.GetMock(true) : Transport;
ListerFactory = ListerFactory ?? MockIListenerUtil.GetMockSetupWithAction((a) => invokingAction = a);
000007FE9236F7A0 mov qword ptr [rbp+30h],rax
000007FE9236F7A4 mov rax,qword ptr [rbp+30h]
000007FE9236F7A8 mov qword ptr [rbp+20h],rax
000007FE9236F7AC mov rcx,qword ptr [rbp+28h]
如果我使用 if 语句或 ?: 运算符,一切都可以正常工作。
Visual Studio 2013
编辑
我已经创建了一个伪最小复制。
class simple
{
public A MyA = null;
public B MyB = null;
public void SetUp()
{
MyA = MyA ?? new A();
MyB = new B();// Put breakpoint here
}
}
如果您在指示的行上设置断点并在调试器中查看 MyA 的值,它仍然为空(仅在 x64 中构建时)。如果您执行下一行,它将设置该值。我无法重现根本没有发生的评估。在反汇编中非常清楚,下一行的执行在分配发生之前就已经开始了。
编辑 2
这里是一个link 到 ms 连接站点
【问题讨论】:
-
更多代码请或我们可以下载代码的某个位置。我希望能够重现该问题。
-
您能否展示更多的反汇编,至少通过
000007FE9236F7AC(jne所在的位置)? -
@rerun 那我没疯。 :) 寻呼 Eric Lippert...
-
注意64位调试器有问题see here
-
@Guvante 这是不同形式的相同问题,但不是调试器。根据程序集,它在错误的位置生成 fld 分配。看起来它可能正在执行不应该的优化。