2

私はWindbgを初めて使用し、値と参照タイプ.NETについていくつかのことを理解しようとしています。これが私が使用しているコードです

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);
    }
}

ここでスリープ状態にする唯一の理由は、実行中のプロセスにWindbgをアタッチする時間を与えるためです。ブレークポイントを設定するのがより良い方法かもしれませんが、とにかくここに私の質問があります。

  1. Windbgがプロセスに接続されると、このスレッド#3に侵入しますが、ご覧のとおり、マネージドthead ID 3のスレッドはありません。このスレッドはデバッガーによって使用されているだけですか?!threadsコマンドで表示されない可能性のある他のスレッドはありますか?もしそうなら、私にすべてのスレッドを与えることができるコマンドはありますか?

0:003>!threads -special
ThreadCount:2
UnstartedThread:0
BackgroundThread:1
PresidentingThread:0
DeadThread:0
Hosted Runtime:no
PreEmptive Lock ID OSID ThreadOBJ State GC GC Alloc Context Domain Count APT Exception

0 1 bbc 0000000000190c50200a020有効000000000027f3ca8:000000027f3fd0 0000000000187e40 0 MTA
2 2 106c 0000000000198430 b220有効0000000000000000:0000000000000000 0000000000187e40 0 MTA(ファイナライザー)

OSID特殊スレッドタイプ
1e98DbgHelper2106c
ファイナライザー

0:003>!CLRStack
OSスレッドID:0xe6c(3)
管理対象スタックをウォークできません。現在のスレッドは
管理対象スレッドではない可能性があります。!threadsを実行して
、プロセス内の管理対象スレッドのリストを取得できます
0:003> kb
RetAddr:Args to Child:Call Site
00000000 77978778 : 0000000000000000 00000000 00000000 0000000000000000 00000000 776d466d:00000000 00000000 00000000 00000000:ntdll!DbgUiRemoteBreakin + 0x38 00000000 00000000 00000000 00000000 00000000 00000000:00000000 00000000 00000000 00000000:ntdll!RtlUserThreadStart + 0x1d 00000000 : ntdll!DbgBreakPoint
00000000
00000000 0000000000000000 00000000
778d8791 : 0000000000000000 0000000000000000 : KERNEL32!BaseThreadInitThunk+0xd
00000000
00000000 0000000000000000 00000000

  1. スレッド0は、私のMainメソッドを実行しているスレッドのようです。スタックオブジェクトのダンプを取得すると、MyStructが表示されず、何らかの理由でMyClassが2回表示されます。なぜ何かアイデアはありますか?

0:000>!CLRStack
OSスレッドID:0xbbc(0)
Child-SP RetAddr Call Site
000000000031edb0 000007fef6b32012 ConsoleApplication2.Program.Main(System.String [])
0:000>!DumpStackObjects
OSスレッドID:0xbbc(0)
RSP / REGオブジェクト名
000000000031edd800000000027f3c90ConsoleApplication2.Program + MyClass
000000000031ede8 00000000027f3c90 ConsoleApplication2.Program + MyClass
000000000031ee00 00000000027f3c70 System.Object [](System.String [])
000000000031ef88 00000000027f3c70 System.Object [](System.String [])
000000003 [](System.String [])
000000000031f198 00000000027f3c70 System.Object [](System.String [])

TIA

4

2 に答える 2

3

実行中のプロセスにアタッチすると、デバッガーがプロセスにスレッドを挿入し、それが現在のスレッドとして選択されます。Liranが指摘しているように、SOSコマンド!threadsは管理対象スレッドのみを一覧表示します。

単純なコンソールアプリケーションの場合、2つの管理対象スレッドが表示されることを期待する必要があります。アプリケーションを実行するメインスレッドと、CLRによって開始されるファイナライザースレッド。私の経験では、それらは常にそれぞれ0と2の番号が付けられています。

この!dsoコマンドは、スタック上の参照を表示します。値の型はリストされていません。そのためには、ローカル用の!clrstackコマンドを使用できます-l。これらが最適化されたコードのためにスタックに配置されることはめったになく、x64では呼び出し規約により、これらを追跡することがさらに困難になることに注意してください。

于 2010-09-29T04:50:51.343 に答える
1
  1. この!Threadsコマンドは、マネージド スレッドのみを表示します (純粋なネイティブ スレッドは破棄されます)。
    すべてのスレッド (管理対象と非管理対象の両方) を表示するには、 を使用できます~~*kb( [where *means "for every thread"]などのコマンドを使用して、ネイティブ スタックをダンプできます)。

  2. この!dsoコマンドは参照タイプのみを表示し、「誤検知」または単に間違ったデータを表示する場合があります (SOS には少しバグのある性質があることがわかります)。

SOS のヘルプから ( !help):

!DumpStackObjects [-verify] [トップ スタック [ボトム スタック]]

このコマンドは、現在のスタックの境界内で見つかったすべての管理対象オブジェクトを表示します。K や !CLRStack などのスタック トレース コマンドと組み合わせると、ローカル変数とパラメーターの値を判断するのに役立ちます。

-verify オプションを使用すると、オブジェクト候補の各非静的 CLASS フィールドが検証されます。これは、誤検知を排除するのに役立ちます。デバッグ シナリオでは、無効なフィールドを持つオブジェクトに関心があることが非常に多いため、デフォルトではオンになっていません。

省略形 !dso を使用して簡潔にすることができます。

于 2010-09-27T21:09:05.300 に答える