Reputation: 6699
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
Upvotes: 2
Views: 1734
Reputation: 1636
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.
Upvotes: 1
Reputation: 116471
When you attach to a running process the debugger injects a thread into the process and that is picked as the current thread. As Liran points out the SOS command !threads
only lists managed threads.
For a simple console application you should expect to see two managed threads; the main thread running the application and the finalizer thread, which is started by the CLR. In my experience they are always numbered 0 and 2 respectively.
The !dso
command shows references on the stack. It doesn't list value types. For that you can use the !clrstack
command with -l
for locals. Keep in mind that these will rarely be placed on the stack for optimized code and on x64 the calling convention makes it even harder to track these.
Upvotes: 3