Share via


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!