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!


Comments (0)

Skip to main content