I am new to Windbg and trying to understand a few things about value and refernece types .NET. Here is the code that i am using
class Program
{
struct MyStruct
{
int x;
int y;
}
class MyClass
{
int x;
int y;
}
static void Main(string[] args)
{
MyStruct s ;
MyClass c = new MyClass();
Thread.Sleep(5 * 60 * 1000);
}
}
The only reason i put sleep here is to give me time to attach Windbg with the running process. I know a better way of doing it might be to put a breakpoint but anyways here are my questions.
0:003> !threads -special
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive Lock
ID OSID ThreadOBJ State GC GC Alloc Context Domain Count APT Exception
0 1 bbc 0000000000190c50 200a020 Enabled 00000000027f3ca8:00000000027f3fd0 0000000000187e40 0 MTA
2 2 106c 0000000000198430 b220 Enabled 0000000000000000:0000000000000000 0000000000187e40 0 MTA (Finalizer)
OSID Special thread type
1 e98 DbgHelper
2 106c Finalizer
0:003> !CLRStack
OS Thread Id: 0xe6c (3)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
0:003> kb
RetAddr : Args to Child : Call Site
0000000077978778 : 00000000
00000000 0000000000000000 00000000
00000000 0000000000000000 : ntdll!DbgBreakPoint
776d466d : 00000000
0000000000000000 00000000
00000000 0000000000000000 00000000
00000000 : ntdll!DbgUiRemoteBreakin+0x38
00000000778d8791 : 00000000
00000000 0000000000000000 00000000
00000000 0000000000000000 : KERNEL32!BaseThreadInitThunk+0xd
00000000 : 00000000
0000000000000000 00000000
00000000 0000000000000000 00000000
00000000 : ntdll!RtlUserThreadStart+0x1d
0:000> !CLRStack
OS Thread Id: 0xbbc (0)
Child-SP RetAddr Call Site
000000000031edb0 000007fef6b32012 ConsoleApplication2.Program.Main(System.String[])
0:000> !DumpStackObjects
OS Thread Id: 0xbbc (0)
RSP/REG Object Name
000000000031edd8 00000000027f3c90 ConsoleApplication2.Program+MyClass
000000000031ede8 00000000027f3c90 ConsoleApplication2.Program+MyClass
000000000031ee00 00000000027f3c70 System.Object[] (System.String[])
000000000031ef88 00000000027f3c70 System.Object[] (System.String[])
000000000031f170 00000000027f3c70 System.Object[] (System.String[])
000000000031f198 00000000027f3c70 System.Object[] (System.String[])
TIA
The !Threads
command displays only managed threads (it will discard purely native threads).
To see all of your threads (both managed an unmanaged), you could use ~
. (you could dump the native stacks using a command such as ~*kb
[where *
means "for every thread"]).
The !dso
command only displays reference types, and sometimes it could display "false positives" or just wrong data (you'll find that SOS have a bit of a buggy nature).
From SOS's help (!help
):
!DumpStackObjects [-verify] [top stack [bottom stack]]
This command will display any managed objects it finds within the bounds of the current stack. Combined with the stack tracing commands like K and !CLRStack, it is a good aid to determining the values of locals and parameters.
If you use the -verify option, each non-static CLASS field of an object candidate is validated. This helps to eliminate false positives. It is not on by default because very often in a debugging scenario, you are interested in objects with invalid fields.
The abbreviation !dso can be used for brevity.