C# NullReferenceException来自一个不可能的位置?
我想知道是否有人遇到过与我相同的情况,C# NullReferenceException来自一个不可能的位置?,c#,.net,wpf,nullreferenceexception,C#,.net,Wpf,Nullreferenceexception,我想知道是否有人遇到过与我相同的情况,NullReferenceException发生在一个不可能的地方 下面是引发异常的完全相同的代码段: private readonly StatePair[] _pairs = { new StatePair(0), new StatePair(1), new StatePair(2) }; public void CommitAll() { var states = new State[_pairs.Length]; // col
NullReferenceException
发生在一个不可能的地方
下面是引发异常的完全相同的代码段:
private readonly StatePair[] _pairs =
{
new StatePair(0),
new StatePair(1),
new StatePair(2)
};
public void CommitAll()
{
var states = new State[_pairs.Length];
// collect in reverse order
for (var i = _pairs.Length - 1; i >= 0; i--)
{
// The only exit of CaptureState() method is a "new State()" statement.
states[i] = _pairs[i].CaptureState();
if (states[i] == null)
throw new ApplicationException("The state captured is null.");
}
// commit in normal order
foreach (var s in states)
{
if (s == null)
throw new ApplicationException("The state is null.");
s.Commit(); // *** NullReferenceException ***
}
}
void Run() // Thread start
{
while (true)
{
CommitAll();
Thread.Sleep(200);
}
}
堆栈跟踪:
System.NullReferenceException: Object reference not set to an instance of an object.
at ...SystemUpdateCoordinator.CommitAll() in ...SystemUpdateCoordinator.cs:line 217
at ...SystemUpdateCoordinator.Run() in ...SystemUpdateCoordinator.cs:line 22
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
从堆栈跟踪中,我们可以看出s.Commit()
抛出NullReferenceException
,因此s
似乎为null,但我们已经检查了null,并在每次CaptureState()之后抛出ApplicationException
。如果CaptureState
现在返回,我们应该从for
的主体中获取ApplicationException
,而不是foreach
内部的NullReferenceException
令人害怕的是,并不是所有用户都会得到异常(这是一个WPF应用程序)。我们有大约10个用户在运行这个新版本,其中只有4个用户遇到了错误,但这在两天内发生了多次。我们在一家大型公司,因此所有用户的环境都受到严格控制,应该是相同的(.NET 4.0,Win 7)
此外,这里还有一些可能有所帮助的详细信息:
是否涉及多线程?
是的,但是唯一可以并发访问的部分是MyPair
对象,在CaptureState
方法中,它持有readerwriterlocksim
中的writer锁。我仔细检查了MyPair
中的其他方法,它们都受到同一readerwriterlocksim
实例的读卡器锁的保护。另外,CaptureState()
每次都返回一个新的实例。所有的rest变量都是局部变量(比如s
),它们不会有线程问题
同时发生任何其他相关错误?
是的,实际上,同一新版本的应用程序发生了另一个错误,这是一个访问冲突错误。它应该与相同,但我不能100%地确定这是导致null引用异常的原因,原因有两个:
这两种情况并不总是同时发生,尽管它们在大多数情况下是同时发生的
如果并发GC错误破坏了内存,导致出现NullReferenceException
,为什么总是发生在同一条语句上?为什么其他地方不会发生这种情况
这个问题困扰了我好几天。我认为这是一个运行时问题,但这不是我可以向其他人证明或证明它是错误的。我还尝试稍微更改一下CommitAll()
方法,看看是否可以得到不同的汇编代码
如果我有更多信息,我会在这里发布更新
==更新1(20150603)===
有人问斯塔克的痕迹是否准确,我想是的
首先,CommitAll()
方法没有内联。我已经转储了汇编代码,它在没有内联的情况下调用Commit
方法
此外,首先这里没有抛出新的ApplicationException()
检查。代码如下所示,因为此处不可能有null:
public void CommitAll()
{
var states = new State[_pairs.Length];
for (var i = _pairs.Length - 1; i >= 0; i--)
{
states[i] = _pairs[i].CaptureState();
}
foreach (var s in states)
{
s.Commit(); // <- Line 209
}
}
另一个说的不一样:
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(1714.ed4): Access violation - code c0000005 (first/second chance not available)
clr!VirtualCallStubManager::ResolveWorker+0x4a3:
000007fe`edb827d8 488b8980000000 mov rcx,qword ptr [rcx+80h] ds:00000101`00000c84=????????????????
0:012> kb
RetAddr : Args to Child : Call Site
000007fe`edb82713 : 00000000`00e2f360 00000000`2c50e740 00000000`00000000 800003ff`825b7314 : clr!VirtualCallStubManager::ResolveWorker+0x4a3
000007fe`edb43585 : 00000000`00000003 000007ff`0442a6b0 00000000`a004a410 00000000`8bd38210 : clr!VirtualCallStubManager::ResolveWorkerStatic+0x213
000007ff`02b416fb : 00000000`b7476e68 00000000`2c50e910 00000000`00e2bfd0 00000000`00000000 : clr!ResolveWorkerAsmStub+0x95
000007ff`02b41344 : 00000000`0a48bc20 00000000`a0444b88 00000000`8bd37108 000007fe`edbe45e4 : 0x7ff`02b416fb
...
000007ff`0245b040 : 00000000`000000fa 00000000`04157e38 00000000`045a09d0 00000000`00000000 : 0x7ff`0245b3e4
Unable to load image C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\79d73b390cca60b8a1c1d1228c771f2f\mscorlib.ni.dll, Win32 error 0n2
*** WARNING: Unable to verify checksum for mscorlib.ni.dll
000007fe`ea7e169c : 00000000`0431c4a0 00000000`045a09d0 00000000`045a09d0 00000000`00000000 : 0x7ff`0245b040
000007fe`ea7e15ab : 00000000`045a09d0 00000000`00000000 00000000`00000000 000007fe`edb85a1f : mscorlib_ni+0x37169c
000007fe`ea876d8d : 00000000`045a09d0 00000000`00000000 00000000`00000000 00000000`00000000 : mscorlib_ni+0x3715ab
000007fe`edb7c9e4 : 00000000`045a09f8 00000000`00000000 00000000`00000000 00000000`00000000 : mscorlib_ni+0x406d8d
000007fe`edb7caf9 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!CallDescrWorker+0x84
000007fe`edb7cb75 : 00000000`2c50f168 00000000`00000001 00000000`2c50f170 00000000`2c50f3c0 : clr!CallDescrWorkerWithHandler+0xa9
000007fe`edb7d0ac : 00000000`2c50f3b8 000007fe`ea774860 00000000`2c50f450 000007fe`ea53ce7c : clr!MethodDesc::CallDescr+0x2a1
000007fe`edc4de50 : 00000000`2c50f860 00000000`2c50f440 00000000`2c50f900 000007fe`ea94df28 : clr!MethodDesc::CallTargetWorker+0x44
000007fe`edbe08e6 : 00000000`1c696620 00000000`2c50f860 00000000`1c696620 00000000`00001000 : clr!ThreadNative::KickOffThread_Worker+0x148
000007fe`edbe087b : 00000000`00000000 00000000`1c696620 ffffffff`fffffffe 00000000`1c696620 : clr!QueueUserWorkItemManagedCallback+0x92
000007fe`edbe07e8 : 000007ff`fffdc000 00000000`00000002 00000000`00000002 000007fe`f51f7163 : clr!PEDecoder::CheckILOnlyImportDlls+0x294
000007fe`edbe094b : ffffffff`ffffffff 00000000`1c696620 00000000`00000000 00000000`00000000 : clr!StubLinkerCPU::X86EmitPushReg+0x135
000007fe`edc4dca0 : 00000000`1c696620 00000000`2c50ff20 00000000`00000001 00000000`00000000 : clr!COMArrayInfo::GetReference+0x12b
000007fe`edd0c736 : 00000000`21062e70 00000000`2c50f918 00000000`1c696620 00000000`00000000 : clr!ThreadNative::KickOffThread+0xc0
00000000`76eb59cd : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!Thread::intermediateThreadProc+0x7d
00000000`770eb891 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
此外,用户正在使用.NET4.0,但所有开发人员的计算机都在使用.NET4.5(但目标是.NET4.0)。这就解释了为什么GC错误只发生在用户身上。Commit()是否包含内部返回null ref的代码(s实际上是!=null)?您能否显示StatePair
的代码,或者至少显示CaptureState
,或者可能显示Commit
?这里的一切看起来都很好,问题一定是更深层次的。这很好,但这对我们没有帮助。你的问题,如帖子所示,没有足够的信息来追踪问题。规则1:它几乎从来都不是运行时bug。规则#2:如果你认为你看到的行为本应是不可能的,那么要么该行为实际上不是不可能的,要么你没有看到你认为自己看到的。假设您发布的代码实际上是正在执行的代码,s
不可能是null
,因此NullReferenceException
是出于其他原因。如果没有可靠地再现该问题,堆栈溢出就无法解释该问题。本机代码的线程问题如果没有正确测试以在多线程环境中运行,则绝对会导致访问冲突。
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(1714.ed4): Access violation - code c0000005 (first/second chance not available)
clr!VirtualCallStubManager::ResolveWorker+0x4a3:
000007fe`edb827d8 488b8980000000 mov rcx,qword ptr [rcx+80h] ds:00000101`00000c84=????????????????
0:012> kb
RetAddr : Args to Child : Call Site
000007fe`edb82713 : 00000000`00e2f360 00000000`2c50e740 00000000`00000000 800003ff`825b7314 : clr!VirtualCallStubManager::ResolveWorker+0x4a3
000007fe`edb43585 : 00000000`00000003 000007ff`0442a6b0 00000000`a004a410 00000000`8bd38210 : clr!VirtualCallStubManager::ResolveWorkerStatic+0x213
000007ff`02b416fb : 00000000`b7476e68 00000000`2c50e910 00000000`00e2bfd0 00000000`00000000 : clr!ResolveWorkerAsmStub+0x95
000007ff`02b41344 : 00000000`0a48bc20 00000000`a0444b88 00000000`8bd37108 000007fe`edbe45e4 : 0x7ff`02b416fb
...
000007ff`0245b040 : 00000000`000000fa 00000000`04157e38 00000000`045a09d0 00000000`00000000 : 0x7ff`0245b3e4
Unable to load image C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\79d73b390cca60b8a1c1d1228c771f2f\mscorlib.ni.dll, Win32 error 0n2
*** WARNING: Unable to verify checksum for mscorlib.ni.dll
000007fe`ea7e169c : 00000000`0431c4a0 00000000`045a09d0 00000000`045a09d0 00000000`00000000 : 0x7ff`0245b040
000007fe`ea7e15ab : 00000000`045a09d0 00000000`00000000 00000000`00000000 000007fe`edb85a1f : mscorlib_ni+0x37169c
000007fe`ea876d8d : 00000000`045a09d0 00000000`00000000 00000000`00000000 00000000`00000000 : mscorlib_ni+0x3715ab
000007fe`edb7c9e4 : 00000000`045a09f8 00000000`00000000 00000000`00000000 00000000`00000000 : mscorlib_ni+0x406d8d
000007fe`edb7caf9 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!CallDescrWorker+0x84
000007fe`edb7cb75 : 00000000`2c50f168 00000000`00000001 00000000`2c50f170 00000000`2c50f3c0 : clr!CallDescrWorkerWithHandler+0xa9
000007fe`edb7d0ac : 00000000`2c50f3b8 000007fe`ea774860 00000000`2c50f450 000007fe`ea53ce7c : clr!MethodDesc::CallDescr+0x2a1
000007fe`edc4de50 : 00000000`2c50f860 00000000`2c50f440 00000000`2c50f900 000007fe`ea94df28 : clr!MethodDesc::CallTargetWorker+0x44
000007fe`edbe08e6 : 00000000`1c696620 00000000`2c50f860 00000000`1c696620 00000000`00001000 : clr!ThreadNative::KickOffThread_Worker+0x148
000007fe`edbe087b : 00000000`00000000 00000000`1c696620 ffffffff`fffffffe 00000000`1c696620 : clr!QueueUserWorkItemManagedCallback+0x92
000007fe`edbe07e8 : 000007ff`fffdc000 00000000`00000002 00000000`00000002 000007fe`f51f7163 : clr!PEDecoder::CheckILOnlyImportDlls+0x294
000007fe`edbe094b : ffffffff`ffffffff 00000000`1c696620 00000000`00000000 00000000`00000000 : clr!StubLinkerCPU::X86EmitPushReg+0x135
000007fe`edc4dca0 : 00000000`1c696620 00000000`2c50ff20 00000000`00000001 00000000`00000000 : clr!COMArrayInfo::GetReference+0x12b
000007fe`edd0c736 : 00000000`21062e70 00000000`2c50f918 00000000`1c696620 00000000`00000000 : clr!ThreadNative::KickOffThread+0xc0
00000000`76eb59cd : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!Thread::intermediateThreadProc+0x7d
00000000`770eb891 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d