公益事業
- WinDbg + SOS、adplus.vbs-公式ページDebugging Tools for Windows-Overviewからダウンロードできます。 シンボルサーバーでWinDbgを構成する方法は、Microsoft Symbol Serverを使用してデバッグシンボルファイルを取得する記事、コマンドのチートシートはこちら 、 ADPlusを使用して「ハング」および「クラッシュ」をトラブルシューティングする記事のadplus.vbsパラメーターの説明にあります。 ;
- デバッグ診断ツールv1.1 ;
- リフレクター
- .NET Framework 2.0用のCLRプロファイラー 、またはより便利ですが、 JetBrains dotTrace (10日間の試用期間)を支払いました。
これらすべてが個別の仮想マシンにインストールされ、メインOSを詰まらせないことが便利です。メインOSは.NETおよびエンターテイメントでのアプリケーション開発にのみ使用します。
.NETアプリケーションのデバッグ
アプリケーションを開発するとき、開発者は通常、完全に制御できるマシンで作業し、さまざまなユーティリティを使用できます。 デバッグ用に、コードをステップ実行し、変更してコンパイルする機能を備えた開発環境があります。 問題なく、いつでもアプリケーションを一時停止して、再起動できます。 ただし、顧客のサーバーでは、システムユーザーに影響を与えることなく、段階的なデバッグのためにアプリケーションを一時停止することはほとんど不可能です。 一般に、顧客のサーバーでアプリケーションをデバッグすると、通常は問題をできるだけ早く解決する必要があります。 シンプルなサービスでは、顧客はお金を失い、顧客は去り、単純な生産サイクルがあり、他の問題が発生する可能性があります。 問題が発生した場合は、一時的に解決するための対策を講じることを強くお勧めします。 これには、アプリケーションのリロード、機能の制限、および状況に対する他のソリューションが含まれる場合があります。
いくつかの問題が発生する可能性があります:アプリケーションのフリーズ、デッドロック、未処理または致命的な例外、データ損失、パフォーマンスの問題、リソースとメモリリーク、不正な機能。 これらの状況はすべて、特定のユーザーだけでなく、システムのすべてのユーザーに影響を与えます。
アプリケーションで問題を引き起こす主な理由は、環境の違い(ハードウェア、ソフトウェア、構成の違い)、および他のシステムとの相互作用です。
クライアント側でアプリケーションをデバッグするのがなぜ難しいのですか? 標準ツールを使用することはできません。サーバーにアクセスすることは困難または不可能であり、問題は非常にまれにしか発生しないか、顧客側にのみ発生します。
アプリケーションの種類に応じて、顧客にアプリケーションをインストールする前にこれらの手順を実行できます。
サーバーアプリケーション:
- お客様のサーバーにデバッグパッケージをインストールします。
- キャラクターサーバーをあなたの側にインストールしてください。
- ロギングおよび監視ツールを追加します。
クライアントアプリケーション:
- キャラクターサーバーをあなたの側にインストールしてください。
- ロギングおよび監視ツールを追加します。
リスクを最小限に抑えるために、顧客に表示される前にエラーを見つけて修正し、さまざまな状況を解決し、Visual Studioの標準とサードパーティのNUnit NCoverの両方で自動テストを行うことをお勧めします。
問題が発生した場合、できるだけ多くの情報を収集することが重要です。これは、エラーの調査と修正に役立ちます。
管理アセンブリアセンブリ構造
あまり詳細には触れません。 それらはさまざまなバージョンで簡単にアクセスできます。さらに使用するものについてのみ説明し、追加の情報源に注意します。
.NET実行可能ファイルは、すべてのWindowsアプリケーションに標準の通常のMS-DOSおよびCOFFヘッダーで始まります。
最初のデータセクションには、CLRヘッダーとデータが含まれます。
最初のセクションには属性CNT_CODE、MEM_EXECUTE、MEM_READがあり、ランタイムに実行されるコードがセクションに含まれていることをローダーに示すことに注意してください。 インポートテーブルでは、アプリケーションを実行している場合の呼び出し「_CorExeMain」を確認できます。 ランタイム環境のメインモジュールのmscoree.dllに実装されています。
詳細については、「 アンマネージAPIリファレンス 」を参照してください。
これらのセグメントの後には、アプリケーション自体のILコードが続きます。 コンパイル結果は中間言語コード(MSIL)です。 これは、プロセッサに依存しない言語です。ネイティブコードよりも高いレベルの言語です。 仕様はこちらで確認できます。
ILコードの後には、メタデータヘッダー、メタデータ自体、アプリケーションリソースを含む追加セグメント、ネイティブアプリケーションコードが続きます(アプリケーションがマネージC ++で開発された場合)。
実行可能ファイルの構造に関する情報は、標準のildasm.exeユーティリティを使用して取得できます。
WinDbg + SOS、adplus.vbsの探索
この段階で、必要なすべてのアプリケーションを既にインストールして構成していることを願っています(Debug Tools ToolsディレクトリーもPATH環境変数に追加してください)。 このテストプログラムについてさらに調査します。
いくつかのナンセンスを行う独自のアプリケーションを作成することができます(必要です)。 このプログラムで重要なのは(o__O、私はそのような考えに傾いていました)、そして重要なのは、ヒープにいくつかのオブジェクトを作成し、いくつかのメソッドを呼び出し、最終的に誤って例外をスローすることです。 文字を使用してアプリケーションのデバッグバージョンを作成しましょう。
アプリケーションを起動します。 そして、アプリケーションのあるディレクトリにこのコマンドを入力します
adplus -quiet -crash -fullonfirst -pn ApplicationForWinDbg.exe
ApplicationForWinDbg.exeはコンパイル済みのexeです。
コンソールアプリケーションで、任意のキーを押します。 すべてを正しく行った場合、 Crash_Mode__Date_ [DATE] __ Time_ [TIME]フォルダーがデバッグツールがインストールされたディレクトリに表示されます。 [日付]と[時間]は、ダンプが作成された日付と時刻です。
ダンプを作成し、それを調べ、同時にCLRの内部を理解します。 この記事では詳細な説明は行いません。主なことは、WinDbg + SOSの使用方法を学ぶことです。 詳細は他の記事で。
WinDbgでダンプを開きます。 次のようなものが得られるはずです。
次のコマンドを実行して、WinDbg-SOS拡張機能をダウンロードします。
0:000> .loadby sos mscorwks
ダウンロードの進行状況を確認するには、次のコマンドを実行します。
0:000> !Eeversion
2.0.50727.3053小売 ワークステーションモード SOSバージョン:2.0.50727.3053小売ビルド
拡張機能がロードされていることを確認し、 ctrl + sを押し、WinDbgが文字をロードするようにアプリケーションへのパスを追加します。 これで調査を開始できます。 アプリケーションにあるスレッドを見てみましょう。
0:000> 〜*
。 0 Id:e8c.11bc一時停止:1 Teb:7ffde000 Unfrozen 開始:ApplicationForWinDbg!COM + _Entry_Point <PERF>(ApplicationForWinDbg + 0x284e)(0011284e) 優先度:0優先度クラス:32アフィニティ:3 1 Id:e8c.13f0一時停止:1 Teb:7ffdd000 Unfrozen 開始:mscorwks!DebuggerRCThread :: ThreadProcStatic(7243237f) 優先度:0優先度クラス:32アフィニティ:3 2 Id:e8c.130c一時停止:1 Teb:7ffdc000 Unfrozen 開始:mscorwks!スレッド:: IntermediateThreadProc(724c1fcf) 優先度:2優先度クラス:32アフィニティ:3
マネージスレッドを見てみましょう。
0:000> !スレッド
スレッドカウント:2 UnstartedThread:0 BackgroundThread:1 PendingThread:0 デッドスレッド:0 ホストされたランタイム:いいえ PreEmptive GC Alloc Lock ID OSID ThreadOBJ状態GCコンテキストドメインカウントAPT例外 0 1 11bc 00529188 a020無効01c903cc:01c91fe8 00524c40 0 MTA 2 2 130c 00537020 b220有効00000000:00000000 00524c40 0 MTA(ファイナライザー)
これから、アプリケーションに2つのマネージスレッド(アプリケーションが実行されているメインのマネージスレッドとFinalizerスレッド)があることがわかります。 そして、もう1つのアンマネージmscorwksスレッドがあります!DebuggerRCThread :: ThreadProcStaticはデバッガースレッドです。 通信仕様は閉じられ、デバッグ情報、段階的なデバッグ機能などが提供されます。このストリームは、アプリケーションのリリースバージョンを作成するかデバッグバージョンを作成するかに関係なく存在します。
アプリケーションのAppDomainsを見てみましょう。
0:000> !ダンプドメイン
--------------------------------------システムドメイン:728ed058 LowFrequencyHeap:728ed07c HighFrequencyHeap:728ed0c8 StubHeap: 728ed114ステージ:オープン名前:なし--------------------------------------共有ドメイン:728ec9a8 LowFrequencyHeap :728ec9cc HighFrequencyHeap:728eca18 StubHeap:728eca64ステージ:OPEN名前:なしアセンブリ:0051c920 --------------------------------- -----ドメイン1:00524c40 LowFrequencyHeap:00524c64 HighFrequencyHeap:00524cb0 StubHeap:00524cfcステージ:OPEN SecurityDescriptor:00526198名前:ApplicationForWinDbg.exeアセンブリ:0051c920 [C:\ WINDOWS \アセンブリ\ GAC_32 \ mscorlib \ 2.0.0.0__b77a5c561934e089 \ mscorlib .dll] ClassLoader:0051c990 SecurityDescriptor:005384a8 Module Name 70da1000 C:\ Windows \ assembly \ GAC_32 \ mscorlib \ 2.0.0.0__b77a5c561934e089 \ mscorlib.dll Assembly:0051ca70 [D:\#Projects \ #Active \ TestApplicationbg \ Application Debug \ ApplicationForWinDbg.exe] ClassLoader:0051cae0 SecurityDescriptor:0053d088モジュール名00202c5c D:\#Projects \ #Active \ Test ApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe
コードが実行されるドメインに加えて、 システムドメイン 、 共有ドメインもあります。 1つは、 共有ドメインのロードと、すべてのユーザードメインのロードとアンロードを担当します。 2番目は、ドメイン中立アセンブラアセンブリのリポジトリとして機能します。 コードはユーザードメインでのみ実行できるため、コードは共有ドメインでは実行されません。
ユーザードメインでは、モジュール-実行可能ファイルdll、exe、その他を確認します。 アセンブラアセンブリには複数のモジュールが含まれている場合がありますが、これらは実行可能ファイルだけでなく、リソースファイルでもあります。 前の例からアセンブリアセンブリcaca70のアドレスを取得し、追加情報を取得します。
0:000> !ダンプアセンブリ0x0051ca70
親ドメイン:00524c40 名前:D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe クラスローダー:0051cae0 SecurityDescriptor:002bed20 モジュール名 00202c5c D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe
モジュール00202c5cに関する情報を見てみましょう。
0:000> !Dumpmodule 0x00202c5c
名前:D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe 属性:PEFile アセンブリ:0051ca70 LoaderHeap:00000000 TypeDefToMethodTableMap:00200038 TypeRefToMethodTableMap:00200048 MethodDefToDescMap:002000a0 FieldDefToDescMap:002000b8 MemberRefToDescMap:002000bc ファイル参照マップ:00200118 AssemblyReferencesMap:0020011c メタデータの開始アドレス:001120e4(1668バイト)
–mtパラメーターを使用すると、モジュールの型に関する情報も取得できます。
0:000> !Dumpmodule -mt 0x00202c5c
名前:D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe 属性:PEFile アセンブリ:thodTableMap:00200038 TypeRefToMethodTableMap:00200048 MethodDefToDescMap:002000a0 FieldDefToDescMap:002000b8 MemberRefToDescMap:002000bc ファイル参照マップ:00200118 AssemblyReferencesMap:0020011c メタデータの開始アドレス:001120e4(1668バイト) このモジュールで定義されているタイプ MT TypeDef名 -------------------------------------------------- ---------------------------- 00203080 0x02000002 ApplicationForWinDbg.Class1 0020300c 0x02000003 ApplicationForWinDbg.Program このモジュールで参照されるタイプ MT TypeRef名 -------------------------------------------------- ---------------------------- 71010508 0x01000001 System.Object 710108ec 0x01000012 System.String 71014258 0x01000013 System.Console 71012b38 0x01000015 System.Int32 0051ca70 LoaderHeap:00000000 TypeDefToMe
コードで定義されているタイプがApplicationForWinDbg.Class1およびApplicationForWinDbg.Programであることを発見しました。 これらのクラスに関する情報は、 EEClassの内部構造に格納されます。 この構造には、インターフェイス、メソッド、フィールドの数、およびそれらの構造などに関する情報が含まれています。
ヒップで何を持っているか見てみましょう:
0:000> !Dumpheap
アドレスMTサイズ 01c71000 0052ccc8 12無料 01c7100c 0052ccc8 12無料 01c71018 0052ccc8 12無料 01c71024 71010b10 72 01c7106c 71010ba0 72 01c710b4 71010c30 72 01c710fc 71010cc0 72 01c71144 71010cc0 72 01c7118c 71010508 12 01c71198 710108ec 20 01c711ac 71010fb8 28 01c711c8 710108ec 160 01c71268 710108ec 216 01c71340 710110cc 100 01c713a4 710113d8 44 01c713d0 70fe40bc 80 01c71420 710108ec 28 01c7143c 710108ec 32 01c7145c 710108ec 20 01c71470 710108ec 52 01c714a4 710108ec 40 …………………………………………………… 01c90398 7101151c 24 01c903b0 710108ec 28 02c71000 0052ccc8 16無料 02c71010 70fe40bc 4096 02c72010 0052ccc8 16無料 02c72020 70fe40bc 528 02c72230 0052ccc8 16無料 02c72240 70fe40bc 4096 02c73240 0052ccc8 16無料 合計5361オブジェクト 統計: MTカウントTotalSizeクラス名 71013dc0 1 12 System.Text.DecoderExceptionFallback 71013d7c 1 12 System.Text.EncoderExceptionFallback 71013ae4 1 16 System.Text.DecoderReplacementFallback 71013a94 1 16 System.Text.EncoderReplacementFallback 71014808 1 20 Microsoft.Win32.SafeHandles.SafeFileMappingHandle 710147b0 1 20 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle 71014724 1 20 System.Text.InternalEncoderBestFitFallback 71012e50 1 20 System.Security.PermissionToken 7100e8b8 1 20 Microsoft.Win32.SafeHandles.SafeFileHandle 71014770 1 24 System.Text.InternalDecoderBestFitFallback 710143c0 1 24 System.IO.TextWriter + SyncTextWriter 710127cc 2 24 System.Security.Permissions.SecurityPermission 71012510 1 24 System.OperatingSystem 71014290 1 28 Microsoft.Win32.Win32Native + InputRecord 71013f24 1 28 System.Text.EncoderNLS 71013c34 1 28 System.IO.Stream + NullStream 71013990 1 28 System.Text.UTF8Encoding 71010fb8 1 28 System.SharedStatics 71013ea4 1 32 System.Text.UTF8Encoding + UTF8Encoder 71012efc 1 32 System.Security.PermissionTokenFactory 710122cc 1 32 Microsoft.Win32.Win32Native + OSVERSIONINFO 710142e4 1 36 System.IO .__ ConsoleStream 71012eb0 1 36 System.Security.Util.TokenBasedSet 71012d18 1 36 System.Security.Permissions.FileIOPermission 710120c8 1 36 System.Int64 [] 710123d4 1 40 Microsoft.Win32.Win32Native + OSVERSIONINFOEX 7101278c 1 44 System.Security.FrameSecurityDescriptor 710113d8 1 44 System.AppDomainSetup 71012874 3 48 System.Security.Permissions.FileIOAccess 71012494 2 48 System.Version 71011e38 2 48 System.Reflection.Assembly 7100e6f4 4 48 System.UInt16 71012c14 2 56 System.Collections.ArrayList + ArrayListEnumeratorSimple 71010ec0 1 56 System.Threading.Thread 71013714 1 68 System.Globalization.CultureTable 710128bc 3 72 System.Security.Util.StringExpressionSet 710125b0 2 72 System.Security.PermissionSet 71010c30 1 72 System.ExecutionEngineException 71010ba0 1 72 System.StackOverflowException 71010b10 1 72 System.OutOfMemoryException 71014608 1 76 System.Text.SBCSCodePageEncoding 710137a8 5 100 System.Globalization.CultureTableItem 710110cc 1 100 System.AppDomain 0052ccc8 7100無料 71012b38 9108 System.Int32 710140d4 2 112 System.IO.StreamWriter 71010a28 6120 System.Text.StringBuilder 71010508 10120 System.Object 710136c4 3 144 System.Globalization.CultureTableRecord 7101291c 6 144 System.Collections.ArrayList 71010cc0 2 144 System.Threading.ThreadAbortException 71011a6c 8160 System.RuntimeType 71011fe4 3 192 System.IO.UnmanagedMemoryStream 710134e8 3204 System.Globalization.CultureInfo 71013850 2 256 System.Globalization.NumberFormatInfo 71012f40 7 392 System.Collections.Hashtable 7101335c 3 684 System.Byte [] 7101303c 7 1008 System.Collections.Hashtable + bucket [] 71012a88 14 1536 System.Int32 [] 70fe40bc 28 9564 System.Object [] 00203 080 1000 12000 ApplicationForWinDbg.Class1 7101151c 1022 25376 System.Char [] 710108ec 3160 82600 System.String 合計5361オブジェクト
答えてみてください、今何行が腰にありますか?
メタデータへのポインターを使用して、ApplicationForWinDbg.Class1クラスに関する情報を取得します。
0:000> !Dumpmt 0x00203080
EEClass:0020135c モジュール:00202c5c 名前:ApplicationForWinDbg.Class1 mdToken:02000002(D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe) BaseSize:0xc ComponentSize:0x0 IFaceMapのIFacesの数:0 VTableのスロット:7
これで、そのEEClassへのポインターにアクセスでき、その説明が表示されます:
0:000> !Dumpclass 0x0020135c
クラス名:ApplicationForWinDbg.Class1 mdToken:02000002(D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe) 親クラス:70da3ef0 モジュール:00202c5c 方法表:00203080 Vtableスロット:4 総メソッドスロット:5 クラス属性:100000 NumInstanceFields:0 NumStaticFields:0
メソッドテーブル00203080へのポインタによって、クラスのすべてのメソッドのリストを見てみましょう。
0:000> !Dumpmt -md 0x00203080
EEClass:0020135c モジュール:00202c5c 名前:ApplicationForWinDbg.Class1 mdToken:02000002(D:\#Projects \ #Active \ TestApplicationNet \ ApplicationForWinDbg \ bin \ Debug \ ApplicationForWinDbg.exe) BaseSize:0xc ComponentSize:0x0 IFaceMapのIFacesの数:0 VTableのスロット:7 -------------------------------------- MethodDescテーブル Entry MethodDesc JIT名 70f66a70 70de4934 PreJIT System.Object.ToString() 70f66a90 70de493c PreJIT System.Object.Equals(System.Object) 70f66b00 70de496c PreJIT System.Object.GetHashCode() 70fd72f0 70de4990 PreJIT System.Object.Finalize() 004b0150 00203078 JIT ApplicationForWinDbg.Class1..ctor() 004b0188 00203060 JIT ApplicationForWinDbg.Class1.Method1(System.String) 004b01d8 0020306c JIT ApplicationForWinDbg.Class1.Method2(Int32)
また、例として、 ApplicationForWinDbg.Class1.Method1とそのコンパイル済みコードに関する情報を見てみましょう。
0:000> !Dumpmd 0x00203060
メソッド名:ApplicationForWinDbg.Class1.Method1(System.String) クラス:0020135c MethodTable:00203080 mdToken:06000001 モジュール:00202c5c IsJitted:はい CodeAddr:004b0188
0:000> !U 0x004b0188
通常のJIT生成コード ApplicationForWinDbg.Class1.Method1(System.String) 004b0188の開始、サイズ3a >>> 004b0188 55 push ebp 004b0189 8bec mov ebp、esp 004b018b 83ec0c sub esp、0Ch 004b018e 894dfc mov dword ptr [ebp-4]、ecx 004b0191 8955f8 mov dword ptr [ebp-8]、edx 004b0194 833d142e200000 cmp dword ptr ds:[202E14h]、0 004b019b 7405 je 004b01a2 004b019d e8dfa21472 mscorwksを呼び出す!JIT_DbgIsJustMyCode(725fa481) 004b01a2 90 nop 004b01a3 8b153020c702 mov edx、dword ptr ds:[2C72030h]( "$") 004b01a9 8b4df8 mov ecx、dword ptr [ebp-8] 004b01ac e86feaaa70 call mscorlib_ni + 0x1bec20(70f5ec20)(System.String.Concat(System.String、System.String)、mdToken:060001c9) 004b01b1 8945f4 mov dword ptr [ebp-0Ch]、eax 004b01b4 8b4df4 mov ecx、dword ptr [ebp-0Ch] 004b01b7 e81c36fc70 call mscorlib_ni + 0x6d37d8(714737d8)(System.Console.WriteLine(System.String)、mdToken:060007c8) 004b01bc 90 nop 004b01bd 90 nop 004b01be 8be5 mov esp、ebp 004b01c0 5dポップebp 004b01c1 c3 ret
すべてのリスティングのために記事が長くなることが判明したため、おそらくここで終了します。 継続を待ちます。 そして、すべてのフィールドの目的のより詳細な説明と、次の記事では、他のコマンドについて説明します。