来自不可能的地方的NullReferenceException?

时间:2015-06-02 16:29:13

标签: 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];

  // 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为空,但我们已经检查了空并抛出ApplicationException在每个CaptureState()之后。如果CaptureState现在返回,我们应该从ApplicationException的正文中获取for,而不是NullReferenceException内的foreach

可怕的是,并非所有用户都获得异常(它是WPF应用程序)。我们有大约10个用户运行这个新版本,其中只有4个符合错误,但它在两天内多次发生。我们在一家大公司工作,因此所有用户的环境都受到限制,应该是相同的(.NET 4.0,Win 7)。

此处还有一些可能有用的细节:

是否涉及多线程?

是的,但唯一可能同时访问的部分是MyPair对象,而在CaptureState方法中,它保存来自ReaderWriterLockSlim的编写器锁。我仔细检查了MyPair中的其他方法,并且所有方法都受到同一ReaderWriterLockSlim实例的读者锁定的保护。此外,CaptureState()每次都会返回实例。所有其余变量都是本地的(如s),他们不会遇到线程问题。

任何其他相关错误同时发生?

是的,实际上在应用程序的新版本发生了另一个错误,这是一个访问冲突错误。它应与this one相同,但由于两个原因,我不能100%确定NullReferenceException的原因:

  1. 这两个并不总是在一起发生,尽管它们在大多数时间里一起发生。
  2. 如果并发GC错误破坏了带来NullReferenceException的内存,为什么它总是会发生在同一个语句中呢?为什么它不会在其他地方发生?
  3. 这个问题困扰了我好几天。我认为它是一个运行时问题,但这不是我可以证明或证明其他人错误的东西。我还尝试稍微更改CommitAll()方法,看看我们是否可以获得不同的汇编代码。

    如果我有更多信息,我会在这里发布更新。

    ====更新1(20150603)====

    有人质疑这条痕迹是否准确,我认为是。

    首先,CommitAll()方法没有内联。我已经转储了汇编代码,它调用Commit方法而没有内联。

    此外,首先,此处没有throw new 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
      }
    }
    

    堆栈跟踪指向第209行,即s.Commit()。所以我添加了一些空检查,堆栈跟踪变为第217行,这正是同一语句的新位置。

    ====更新2(20150609)====

    崩溃只发生在过去一周,但奇怪的是WER(Windows错误报告)没有产生迷你崩溃转储。事件日志仍然说:

      

    应用程序:MyApp.exe
      框架版本:v4.0.30319
      说明:由于.NET运行时在IP 000007FEEC0F25E8(000007FEEC0B0000)中出现内部错误而导致进程终止,退出代码为80131506.

    与之前的错误日志不同,显示它是访问冲突。用户说他没有看到WER对话框,所以应用程序突然崩溃了。

    所以我只能检查旧崩溃中的旧转储。

    其中一人说这是一个着名的并发GC问题&#34;:

    This dump file has an exception of interest stored in it.
    The stored exception information can be accessed via .ecxr.
    (2c90.381c): Access violation - code c0000005 (first/second chance not available)
    clr!WKS::gc_heap::mark_object_simple+0x19a:
    000007fe`eb13dc87 f70100000080    test    dword ptr [rcx],80000000h ds:00000000`00000000=????????
    0:008> kb
    RetAddr           : Args to Child                                                           : Call Site
    000007fe`eb13dd8e : 00000000`b2103c48 00000000`2c92d850 00000000`2c92e9c0 00000000`b2023f08 : clr!WKS::gc_heap::mark_object_simple+0x19a
    000007fe`eb1de7be : 00000000`b2103c48 00000000`2c92e9c0 00000000`2c92c2e0 00000000`2c92d7b0 : clr!WKS::GCHeap::Promote+0x79
    000007fe`eb1e04ec : 00000000`2c92bec0 00000000`00000007 00000000`00000002 00000000`00000071 : clr!GcEnumObject+0x37
    000007fe`eb1dfdd5 : 000007fe`00000000 00000000`00000000 00000000`00000000 000007fe`00000008 : clr!GcInfoDecoder::EnumerateLiveSlots+0x5dd
    000007fe`eb1dea47 : 00000000`00080000 00000000`00000000 00000000`0230b540 00000000`2c92c2e0 : clr!EECodeManager::EnumGcRefs+0x13d
    000007fe`eb09109f : 00000000`00000000 000007ff`02668548 00000000`2c92d7b0 00000000`00000000 : clr!GcStackCrawlCallBack+0x1e2
    000007fe`eb090a6b : 00000000`2c92cb50 00000000`00000000 00000000`00000002 00000000`00000000 : clr!Thread::MakeStackwalkerCallback+0x2f
    000007fe`eb0900f2 : 00000000`1fc3ab10 00000000`1fc3ab10 000000f8`00000000 00000000`00000002 : clr!Thread::StackWalkFramesEx+0x8d
    000007fe`eb1de6e8 : 00000000`00000000 00000000`00000001 00000000`00000000 00000000`1fc3ab10 : clr!Thread::StackWalkFrames+0xb1
    000007fe`eb13d831 : 00000000`00000000 00000000`2c92d880 00000000`00000000 00000000`023ade80 : clr!CNameSpace::GcScanRoots+0x1a4
    000007fe`eb13de6d : 00000000`00000000 00000000`00000000 000007fe`eb8ea160 000007fe`eb13e6b6 : clr!WKS::gc_heap::mark_phase+0xe1
    000007fe`eb29fcfd : 00000107`e77ad732 00000000`2c92d959 00000000`00000000 00000000`00000000 : clr!WKS::gc_heap::gc1+0xae
    000007fe`eb13e44e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!WKS::gc_heap::garbage_collect+0x42e
    000007fe`eb13d3fe : 00000000`00000030 00000000`00000002 000007fe`eb060000 00000000`00000000 : clr!WKS::GCHeap::GarbageCollectGeneration+0x14e
    000007fe`eb13d12e : 00000000`0000001d 00000000`b2526b80 00000000`00000002 00000000`00000030 : clr!WKS::gc_heap::try_allocate_more_space+0x25f
    000007fe`eb08d418 : 000007fe`e8b93028 00000000`00000030 00000000`00000002 00000000`2c92ddf0 : clr!FastAllocateObject+0x73e
    Unable to load image C:\Windows\assembly\NativeImages_v4.0.30319_64\System.Core\84fa340f30d1921e0d8817f9344ee367\System.Core.ni.dll, Win32 error 0n2
    *** WARNING: Unable to verify checksum for System.Core.ni.dll
    000007fe`e8b25049 : 000007fe`e8b93028 00000000`b2526b00 00000000`b2526b00 000007fe`e8b24f9a : clr!JIT_NewFast+0xb8
    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`ea18e458 : 00000000`b2526b00 00000000`00000004 00000000`b2526b00 00000000`00000000 : System_Core_ni+0x2a5049
    000007fe`e8b37280 : 000007fe`e88849d8 000007fe`ea17efb0 00000000`0328be48 00000000`b24ee798 : mscorlib_ni+0x3ae458
    000007ff`027790bc : 000007fe`e88dc738 00000000`b2524ed0 00000000`03137038 00000000`2c92dde8 : System_Core_ni+0x2b7280
    000007ff`027789a0 : 00000000`00000000 00000000`00000000 000007ff`03b5ba48 00000000`067059f0 : 0x7ff`027790bc
    ...
    000007fe`ea15169c : 00000000`04118280 00000000`0416ea50 00000000`0416ea50 00000000`00000000 : 0x7ff`024799c0
    000007fe`ea1515ab : 00000000`0416ea50 00000000`00000000 00000000`00000000 000007fe`eb0a5a1f : mscorlib_ni+0x37169c
    000007fe`ea1e6d8d : 00000000`0416ea50 00000000`00000000 00000000`00000000 00000000`00000000 : mscorlib_ni+0x3715ab
    000007fe`eb09c9e4 : 00000000`0416ea78 00000000`00000000 00000000`00000000 00000000`00000000 : mscorlib_ni+0x406d8d
    000007fe`eb09caf9 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!CallDescrWorker+0x84
    000007fe`eb09cb75 : 00000000`2c92ef48 00000000`00000001 00000000`2c92ef50 00000000`2c92f1a0 : clr!CallDescrWorkerWithHandler+0xa9
    000007fe`eb09d0ac : 00000000`2c92f198 000007fe`ea0e4860 00000000`2c92f230 000007fe`e9eace7c : clr!MethodDesc::CallDescr+0x2a1
    000007fe`eb16de50 : 00000000`2c92f640 00000000`2c92f220 00000000`2c92f6e0 000007fe`ea2bdf28 : clr!MethodDesc::CallTargetWorker+0x44
    000007fe`eb1008e6 : 00000000`1fc3ab10 00000000`2c92f640 00000000`1fc3ab10 00000000`00001000 : clr!ThreadNative::KickOffThread_Worker+0x148
    000007fe`eb10087b : 00000000`00000000 00000000`1fc3ab10 ffffffff`fffffffe 00000000`1fc3ab10 : clr!QueueUserWorkItemManagedCallback+0x92
    000007fe`eb1007e8 : 00000000`00000480 00000000`004d0000 00000000`00000000 00000000`00000478 : clr!PEDecoder::CheckILOnlyImportDlls+0x294
    000007fe`eb10094b : ffffffff`ffffffff 00000000`1fc3ab10 00000000`00000000 00000000`00000000 : clr!StubLinkerCPU::X86EmitPushReg+0x135
    000007fe`eb16dca0 : 00000000`1fc3ab10 00000000`2c92fd80 00000000`00000001 00000000`00000000 : clr!COMArrayInfo::GetReference+0x12b
    000007fe`eb22c736 : 00000000`28ef64b0 00000000`2c92f6f8 00000000`1fc3ab10 00000000`772cb98e : clr!ThreadNative::KickOffThread+0xc0
    00000000`771959cd : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!Thread::intermediateThreadProc+0x7d
    00000000`772cb891 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
    00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
    

    另一个说不同的东西:

    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
    

    此外,用户使用的是.NET 4.0,但所有开发人员的计算机都使用的是.NET 4.5(但目标是.NET 4.0)。这就解释了为什么GC错误只发生在用户身上。

0 个答案:

没有答案