Let's say my application has two threads A and B and each thread throws an exception. Can I determine what thread has raised which exception by using ~{threadid}s
and then running !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:
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):
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. This may confuse developers who work with WinDbg for the first time. So don't worry, if you see some exceptions in the output of !dumpheap -stat -type Exception
, eg in a simple HelloWorld application:
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
. Note that WinDbg only displays one #
, although there are exceptions on other threads as well. I don't know how to figure it out on native side.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.