简体   繁体   English

确定从转储文件中抛出异常的线程

[英]Determining thread that throw an exception from a dump file

Let's say my application has two threads A and B and each thread throws an exception. 假设我的应用程序有两个线程A和B,每个线程抛出一个异常。 Can I determine what thread has raised which exception by using ~{threadid}s and then running !pe ? 我可以通过使用~{threadid}s然后运行!pe来确定哪个线程引发了哪个异常?

Usually there is only one thread that was throwing the exception which causes the application to terminate. 通常只有一个线程抛出异常导致应用程序终止。 That said, I saw it happen during a debugging session where the thread with the exception was freezed and other threads were resumed. 也就是说,我看到它发生在调试会话期间,其中具有异常的线程被冻结并且其他线程被恢复。

The .NET !threads command will list the .NET threads and the exceptions on each thread: .NET !threads命令将列出每个线程上的.NET线程和异常:

0:000> !threads
ThreadCount: 6
UnstartedThread: 0
BackgroundThread: 2
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                              PreEmptive                                                Lock
       ID OSID        ThreadOBJ     State   GC     GC Alloc Context                  Domain           Count APT Exception
   0    1 251c 00000000003deff0   201a220 Enabled  00000000027846f8:0000000002785fd0 0000000000382ca0     0 MTA
   2    2 2b10 0000000000a88280      b220 Enabled  0000000000000000:0000000000000000 0000000000382ca0     0 MTA (Finalizer)
   3    3 255c 0000000000aacac0      b020 Enabled  00000000027862b8:0000000002787fd0 0000000000382ca0     0 MTA System.ArgumentException (0000000002786090)
   4    4 2a48 0000000000aad5b0      b020 Enabled  000000000278a290:000000000278bfd0 0000000000382ca0     0 MTA System.NotImplementedException (000000000278a070)
   5    5 2e50 0000000000aa20d0      b020 Enabled  0000000002788268:0000000002789fd0 0000000000382ca0     0 MTA System.OutOfMemoryException (0000000002788048)
   6    6  d50 0000000000aa2e00      b020 Enabled  000000000278c280:000000000278dfd0 0000000000382ca0     0 MTA System.Threading.ThreadInterruptedException (000000000278c060)

You can then switch to the thread listed as ID and dump the exception on that thread ( ~xs;!pe or ~xe!pe where x is the ID): 然后,您可以切换到列为ID的线程并在该线程上转储异常( ~xs;!pe~xe!pe ,其中x是ID):

0:004> ~3e!pe
Exception object: 0000000002786090
Exception type: System.ArgumentException
Message: This method does not have arguments.
InnerException: <none>
StackTrace (generated):
    SP               IP               Function
    000000000112F100 000007FF0017055F MultiException!MultiException.Program.ThrowException1()+0x5f
    000000000112F140 000007FEEB4E2BBC mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x9c
    000000000112F190 000007FEEB57AADE mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+0x4e

StackTraceString: <none>
HResult: 80070057
0:004> ~4e!pe
Exception object: 000000000278a070
Exception type: System.NotImplementedException
Message: This method does nothing but thorwing this exception.
InnerException: <none>
StackTrace (generated):
    SP               IP               Function
    000000000135F2C0 000007FF0017067F MultiException!MultiException.Program.ThrowException2()+0x5f
    000000000135F300 000007FEEB4E2BBC mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x9c
    000000000135F350 000007FEEB57AADE mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+0x4e

StackTraceString: <none>
HResult: 80004001

Also important to know: .NET pre-allocates some exceptions in memory so that they can be thrown later. 同样重要的是要知道:.NET在内存中预先分配了一些异常,以便以后可以抛出它们。 This may confuse developers who work with WinDbg for the first time. 这可能会使首次使用WinDbg的开发人员感到困惑。 So don't worry, if you see some exceptions in the output of !dumpheap -stat -type Exception , eg in a simple HelloWorld application: 所以不要担心,如果你在输出中看到一些例外!dumpheap -stat -type Exception ,例如在一个简单的HelloWorld应用程序中:

0:000> !dumpheap -stat -type Exception
total 7 objects
Statistics:
      MT    Count    TotalSize Class Name
78e4421c        1           12 System.Text.DecoderExceptionFallback
78e441d8        1           12 System.Text.EncoderExceptionFallback
78e4108c        1           72 System.ExecutionEngineException
78e40ffc        1           72 System.StackOverflowException
78e40f6c        1           72 System.OutOfMemoryException
78e4111c        2          144 System.Threading.ThreadAbortException
Total 7 objects

In unmanaged code, threads that threw an exception are marked with # when displaying the threads using ~ : 在非托管代码中,当使用~显示线程时,抛出异常的线程用#标记:

0:000> ~
.  0  Id: 2b14.251c Suspend: 1 Teb: 000007ff`fffde000 Unfrozen
   1  Id: 2b14.71c Suspend: 1 Teb: 000007ff`fffdb000 Unfrozen
   2  Id: 2b14.2b10 Suspend: 1 Teb: 000007ff`fffd9000 Unfrozen
#  3  Id: 2b14.255c Suspend: 1 Teb: 000007ff`fffd7000 Unfrozen
   4  Id: 2b14.2a48 Suspend: 1 Teb: 000007ff`fffd5000 Unfrozen
   5  Id: 2b14.2e50 Suspend: 1 Teb: 000007ff`fffd3000 Unfrozen
   6  Id: 2b14.d50 Suspend: 1 Teb: 000007ff`fff0e000 Unfrozen

If you can't see the # , then it is typically hidden behind the . 如果你看不到# ,那么它通常隐藏在后面. . You can switch to this thread using ~#s . 你可以使用~#s切换到这个线程。 Note that WinDbg only displays one # , although there are exceptions on other threads as well. 请注意,WinDbg只显示一个# ,尽管其他线程也有例外。 I don't know how to figure it out on native side. 我不知道如何在原生方面解决这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM