提问人:Jeffrey Zhao 提问时间:6/3/2015 最后编辑:CommunityJeffrey Zhao 更新时间:6/10/2015 访问量:1163
NullReferenceException 来自一个不可能的地方?
NullReferenceException from an impossible place?
问:
我想知道是否有人曾经和我遇到过同样的情况,发生在一个不可能的地方。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()
从堆栈跟踪中,我们可以看出 throws,所以看起来是 null,但我们已经检查了 null 并在每个 .如果现在返回,我们应该从正文而不是内部得到一个。s.Commit()
NullReferenceException
s
ApplicationException
CaptureState()
CaptureState
ApplicationException
for
NullReferenceException
foreach
可怕的是,并非所有用户都会收到异常(这是一个 WPF 应用程序)。我们大约有 10 个用户运行这个新版本,其中只有 4 个遇到错误,但它在两天内多次发生在他们身上。我们是一家大公司,因此所有用户的环境都受到限制控制,并且应该是相同的(.NET 4.0、Win 7)。
此外,这里还有一些可能会有所帮助的细节:
是否涉及多线程?
是的,但唯一的部分可能是同时访问对象,并且在 method 中它持有来自 .我已经仔细查看了其他方法,所有这些方法都受到同一实例的读取器锁的保护。此外,每次都返回一个新实例。所有其余变量都是局部变量(如),它们不会有线程问题。MyPair
CaptureState
ReaderWriterLockSlim
MyPair
ReaderWriterLockSlim
CaptureState()
s
同时发生任何其他相关错误吗?
是的,实际上,同一新版本的应用程序还发生了另一个错误,即访问冲突错误。它应该和这个一样,但我不能 100% 确定这是原因,原因有两个:NullReferenceException
- 这两者并不总是一起发生,尽管它们在大多数时候一起发生。
- 如果并发 GC 错误损坏了内存,从而带来了 ,为什么它总是发生在相同的语句中?为什么它不会发生在其他地方?
NullReferenceException
这个问题困扰了我好几天。我将其视为运行时问题,但这不是我可以向其他人证明或证明它错误的东西。我也在尝试稍微改变一下方法,看看我们是否可以获得不同的汇编代码。CommitAll()
如果我有更多信息,我会在这里发布更新。
==== 更新 1 (20150603) ====
有人问,鲜明的痕迹是否准确,我认为是。
首先,该方法没有内联。我已经转储了汇编代码,它调用了没有内联的方法。CommitAll()
Commit
此外,首先这里没有检查。代码很简单,因为这里不可能有 null:throw new ApplicationException()
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 行,即 .因此,我添加了一些 null 检查,堆栈跟踪变为第 217 行,这正是同一语句的新位置。s.Commit()
==== 更新 2 (20150609) ====
崩溃在过去一周只发生过一次,但奇怪的是,WER(Windows 错误报告)没有生成小型崩溃转储。事件日志仍然显示:
应用: MyApp.exe
Framework 版本: v4.0.30319
说明: 由于 IP 为 000007FEEC0F25E8 (000007FEEC0B0000) 的 .NET 运行时内部错误,退出代码为 80131506,进程已终止。
这与以前的错误日志不同,明确指出这是访问违规。用户说他没有看到 WER 对话框,因此应用程序突然崩溃。
所以我只能检查旧崩溃中的旧转储。
其中一位说这是一个“著名的并发 GC 问题”:
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 错误只发生在用户身上。
答: 暂无答案
评论
StatePair
CaptureState
Commit
s
null
NullReferenceException