Windbg QuickStart guide (Part 3 - Crashes)
The approach you will take for debugging crashes is very similar between looking at the live process vs looking at a crash dump, there are some small differences that I will talk about in this post.
The first question: What is wrong?
If the program is throwing an exception and exiting
If the program has just crashed, the easiest thing to do it to attach a debugger to the process and see the last exception in the stack
0:005> .loadby sos clr
The !threads command will show me all threads, the thread with an exception will have an exception on top of the stack
0:005> !threads
PDB symbol for clr.dll not loaded
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 14d0 00492eb8 2a020 Preemptive 02639428:00000000 00483e38 0 MTA System.InvalidOperationException 024f2968
3 2 14f8 0049dd78 2b220 Preemptive 00000000:00000000 00483e38 0 MTA (Finalizer)
Now we use the !pe command to dump the exception object
0:005> !pe 024f2968
Exception object: 024f2968
Exception type: System.InvalidOperationException
Message: Path does not exist!
InnerException: <none>
StackTrace (generated):
SP IP Function
001FECE8 00520155 CompareCSV!CompareCSV.Program.Main(System.String[])+0xd5
StackTraceString: <none>
HResult: 80131509
Ok, now we know that it is a path does not exist exception, but which path? We can do this in two ways, if it is a small program like the one I have here I could do !dso
0:000> !dso
OS Thread Id: 0x11fc (0)
ESP/REG Object Name
001FEB88 024f2968 System.InvalidOperationException
001FEBD0 024f2968 System.InvalidOperationException
001FEC20 024f22a4 System.Object[] (System.String[])
001FEC50 024f22a4 System.Object[] (System.String[])
001FEC98 024f22a4 System.Object[] (System.String[])
001FECA8 024f22bc System.String c:\invalid1
001FECC8 024f2968 System.InvalidOperationException
001FECCC 024f2968 System.InvalidOperationException
001FECE8 024f29bc System.String Path does not exist!
001FECEC 024f2968 System.InvalidOperationException
001FECF8 024f22a4 System.Object[] (System.String[])
001FED90 024f22a4 System.Object[] (System.String[])
001FEEF4 024f22a4 System.Object[] (System.String[])
001FEF2C 024f22a4 System.Object[] (System.String[])
Another way to do this would be showing the CLRStack with the parameters
0:000> !clrstack -p
OS Thread Id: 0x11fc (0)
Child SP IP Call Site
001fec2c 7613b9bc [HelperMethodFrame: 001fec2c]
001fece8 00520155 CompareCSV.Program.Main(System.String[]) [d:\Projects\CompareCSV\CompareCSV\Program.cs @ 25]
PARAMETERS:
args (0x001fecf8) = 0x024f22a4
And now I can dump the args passed to main, the !do command will not be very helpful since it is an array
0:000> !do 0x024f22a4
Name: System.String[]
MethodTable: 6b4dfc38
EEClass: 6b1b7a50
Size: 24(0x18) bytes
Array: Rank 1, Number of elements 2, Type CLASS
Fields:
None
The right thing to use is !da, which will list the array items
0:000> !da 0x024f22a4
Name: System.String[]
MethodTable: 6b4dfc38
EEClass: 6b1b7a50
Size: 24(0x18) bytes
Array: Rank 1, Number of elements 2, Type CLASS
Element Methodtable: 6b52cb5c
[0] 024f22bc
[1] 024f22e0
Now I can dump the objects and see the invalid paths!
0:000> !do 024f22bc
Name: System.String
MethodTable: 6b52cb5c
EEClass: 6b15431c
Size: 36(0x24) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: c:\invalid1
Fields:
MT Field Offset Type VT Attr Value Name
6b52e784 40000aa 4 System.Int32 1 instance 11 m_stringLength
6b52d564 40000ab 8 System.Char 1 instance 63 m_firstChar
6b52cb5c 40000ac c System.String 0 shared static Empty
>> Domain:Value 003f7838:NotInit <<
0:000> !do 024f22e0
Name: System.String
MethodTable: 6b52cb5c
EEClass: 6b15431c
Size: 36(0x24) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: c:\invalid2
Fields:
MT Field Offset Type VT Attr Value Name
6b52e784 40000aa 4 System.Int32 1 instance 11 m_stringLength
6b52d564 40000ab 8 System.Char 1 instance 63 m_firstChar
6b52cb5c 40000ac c System.String 0 shared static Empty
>> Domain:Value 003f7838:NotInit <<
If the program is Behaving in an unexpected way
There are various types of problems that could cause unexpected behavior, but the one I hit the most is first chance exceptions taking the code in some unexpected path, for more details check This post.
Hope you find that helpful!