.Net应用程序软件崩溃调试
排查软件崩溃问题,最重要的一点就是找到软件出错点,相比较C++应用程序来说,.Net应用程序会稍有不同。
通常,排查软件崩溃问题的思路是
1:确认出错的函数
2:确认出错的操作指令
步聚1:
使用~*kbn显示所有线程调用线,找到异常线程
. 0 Id: 1b8c.1ee4 Suspend: 1 Teb: 7ffdf000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0012eb94 77f05aec 0dce6924 00000002 0012ebe8 ntdll!KiFastSystemCallRet
01 0012eb98 0dce6924 00000002 0012ebe8 00000001 ntdll!ZwWaitForMultipleObjects+0xc
02 0012ec34 77e2f10a 0012ebe8 0012ec5c 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
03 0012ec7c 77e2f27e 00000002 7ffdc000 00000000 KERNEL32!WaitForMultipleObjectsExImplementation+0xe0
04 0012ec98 77e42ecd 00000002 0012eccc 00000000 KERNEL32!WaitForMultipleObjects+0x18
05 0012ed04 77e42f6a 0012ede4 00000001 00000001 KERNEL32!WerpReportFaultInternal+0x186
06 0012ed18 77e42cf8 0012ede4 00000001 0012edb4 KERNEL32!WerpReportFault+0x70
07 0012ed28 77e42c77 0012ede4 00000001 acf9c09b KERNEL32!BasepReportFault+0x20
08 0012edb4 77f35944 00000000 77edd674 00000000 KERNEL32!UnhandledExceptionFilter+0x1af
09 0012edbc 77edd674 00000000 0012ffd4 77f10420 ntdll!__RtlUserThreadStart+0x62
0a 0012edd0 77edd50c 00000000 00000000 00000000 ntdll!_EH4_CallFilterFunc+0x12
0b 0012edf8 77f06299 fffffffe 0012ffc4 0012ef0c ntdll!_except_handler4+0x8e
0c 0012ee1c 77f0626b 0012eee4 0012ffc4 0012ef0c ntdll!ExecuteHandler2+0x26
0d 0012eecc 77f060f7 0012eee4 0012ef0c 0012eee4 ntdll!ExecuteHandler+0x24
0e 0012eecc 0dce969b 0012eee4 0012ef0c 0012eee4 ntdll!KiUserExceptionDispatcher+0xf
0f 0012f240 79222b54 e0434352 00000001 00000005 KERNELBASE!RaiseException+0x58
10 0012f2d0 79222d89 02b4c758 00000000 00000000 clr!RaiseTheExceptionInternalOnly+0x276
11 0012f390 7a03fdbd 02b4bbb0 02b4c758 02b4b82c clr!IL_Throw+0x14c
12 0012f3a4 7a476e85 0025eca8 0012f410 0012f3d0 mscorlib_ni+0x7bfdbd
13 0012f3e4 791421bb 0012f428 004025f7 0012f470 mscorlib_ni+0xbf6e85
1 Id: 1b8c.d88 Suspend: 2 Teb: 7ffde000 Unfrozen
# ChildEBP RetAddr Args to Child
00 007efdc4 77f05aec 0dce6924 00000003 007efe18 ntdll!KiFastSystemCallRet
01 007efdc8 0dce6924 00000003 007efe18 00000001 ntdll!ZwWaitForMultipleObjects+0xc
02 007efe64 77e2f10a 007efe18 007efe8c 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
03 007efeac 77e2f27e 00000003 7ffdc000 00000000 KERNEL32!WaitForMultipleObjectsExImplementation+0xe0
04 007efec8 79253a58 00000003 007efef0 00000000 KERNEL32!WaitForMultipleObjects+0x18
05 007eff2c 79253996 ac66921a 00000000 00000000 clr!DebuggerRCThread::MainLoop+0xd9
06 007eff5c 792538d1 ac6692ce 00000000 00000000 clr!DebuggerRCThread::ThreadProc+0xca
07 007eff88 77e31154 00000000 007effd4 77f1b299 clr!DebuggerRCThread::ThreadProcStatic+0x83
08 007eff94 77f1b299 00000000 70c5a12d 00000000 KERNEL32!BaseThreadInitThunk+0xe
09 007effd4 77f1b26c 7925388c 00000000 00000000 ntdll!__RtlUserThreadStart+0x70
0a 007effec 00000000 7925388c 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b
如上所示,发现0号线程中有一个调用栈为 UnhandledExceptionFilter ,即可确定0号线程为异常线程
步聚2:
切换到异常线程,对于本例为0号线程
0:000> ~0s
eax=00000000 ebx=0012edd0 ecx=0012e0cc edx=00000020 esi=00000002 edi=00000000
eip=77f06194 esp=0012ed80 ebp=0012ee1c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
77f06194 c3 ret
步聚3:
加载sos.dll(提供调试clr内部环境相关信息),注意sos.dll需与当前.net程序加载的clr版本相符合,其所在路径如下所示,其中v4.0.30319 为版本号
0:000> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
步聚4:
使用 !pe -lines 显示异常信息
0:000> !pe -lines
Exception object: 02b4c758
Exception type: System.ArgumentOutOfRangeException
Message: 索引超出范围。必须为非负值并小于集合大小。
InnerException: <none>
StackTrace (generated):
SP IP Function
0012F398 7A03FDBD mscorlib_ni!System.ThrowHelper.ThrowArgumentOutOfRangeException()+0x49
0012F3AC 7A476E85 mscorlib_ni!System.Collections.Generic.List`1[[System.Int32, mscorlib]].get_Item(Int32)+0x234d15
0012F3BC 003E010A ConsoleApplication1!ConsoleApplication1.Program.f(Int32, Int32)+0x4a
0012F3D8 003E00A6 ConsoleApplication1!ConsoleApplication1.Program.Main(System.String[])+0x36
到此就确定了出错的函数为ConsoleApplication1!ConsoleApplication1.Program.f(Int32, Int32),其中调用mscorlib_ni!System.Collections.Generic.List`1[[System.Int32, mscorlib]].get_Item(Int32) 时产生了一个 System.ArgumentOutOfRangeException异常