次の方法で共有


CLR デバッグの概要

共通言語ランタイム (CLR: Common Language Runtime) のデバッグ API を使用することで、ツールの販売元は、CLR 環境で実行するアプリケーションをデバッグするためのデバッガーを作成できます。 CLR がサポートするすべての種類のコードをデバッグできます。

CLR デバッグ API は、主にアンマネージ コードで実装されています。 したがって、デバッグ API は、コンポーネント オブジェクト モデル (COM: Component Object Model) インターフェイスのセットとして提供されます。 この API は、次の要素で構成されます。

  • CLR によって実装される COM オブジェクトとインターフェイスのコレクション。

  • デバッガーが実装する必要のある COM コールバック インターフェイスのコレクション。

この概要は、次のセクションで構成されています。

  • CLR デバッグのシナリオ

  • API のカテゴリ

  • プログラムへのアタッチまたはプログラムの起動

  • 実行の制御

  • プログラムの状態の確認

  • プログラムの状態の変更

  • エディット コンティニュの使用

  • 関数の評価

  • コードの動的な挿入

  • サポートされる環境

  • 関連トピック

CLR デバッグのシナリオ

以下のセクションでは、共通言語ランタイムのデバッグ API による一般的なデバッグ シナリオの処理方法について説明します。 一部のシナリオはランタイムによって直接サポートされますが、現在のメソッドとの相互運用を通じてサポートされるシナリオもあります。

アウトプロセス デバッグ

アウトプロセス デバッグのデバッガーは、デバッグ対象プロセスとは別のプロセス (デバッグ対象の外部プロセス) です。 このシナリオでは、デバッガーとデバッグ対象との通信が少ない ため、プロセスの状態をより正確に把握することができます。

CLR デバッグ API は、アウトプロセス デバッグを直接サポートします。 この API は、デバッガーとデバッグ対象のマネージ部分との間のすべての通信を処理し、マネージ コードのデバッグをサポートします。

CLR デバッグ API はアウトプロセスで実行されますが、スレッド同期などの一部のデバッグ ロジックは、デバッグ対象のインプロセスで実行されます。 多くの場合、この実装の詳細はデバッガーに対して透過的にする必要があります。 スレッド同期の詳細については、「CLR デバッグのアーキテクチャ」を参照してください。 アウトプロセスの欠点は、API のデバッグ時にクラッシュ ダンプを使用できないという点です。

インプロセス デバッグ

.NET Framework Version 1.0 および 1.1 では、CLR デバッグ API は制限されたインプロセス デバッグをサポートしていました。インプロセス デバッグでは、プロファイラーでデバッグ API の検査機能を使用できました。 .NET Framework 2.0 では、インプロセス デバッグは、プロファイル API との整合性が強化された一連の機能に置き換えられました。 これらの変更の詳細については、「プロファイリングの概要」でスタック スナップショットおよびオブジェクト検査の各機能を参照してください。

リモート プロセス デバッグ

リモート プロセス デバッグでは、デバッガーのユーザー インターフェイスはデバッグ対象プロセスとは別のコンピューター上にあります。 このシナリオは、デバッガーとデバッグ対象を同一コンピューター上で実行するとデバッガーがデバッグ対象に干渉する場合に便利です。 この干渉は次のような原因で発生します。

  • リソースの制約。

  • 場所の依存関係。

  • オペレーティング システムの妨げになるバグ。

CLR デバッグ API は、リモート プロセス デバッグを直接サポートしていません。 それでも、CLR デバッグ API を使用しているデバッガーは、デバッグ対象プロセスの外部に存在する必要があります。 したがって、このソリューションでは、デバッグ対象があるコンピューターにプロキシ プロセスが必要となります。

アンマネージ コード デバッグ

同じプロセスにマネージ コードとアンマネージ コードが共存することがよくあります。 そのため、一般的には、両方の種類のコードを同時にデバッグする必要があります。

CLR デバッグ API は、マネージ コードとアンマネージ コードの境界でステップ実行される機能をサポートしていますが、アンマネージ コードのデバッグは直接サポートしていません。 ただし、CLR デバッグ API は、Win32 のデバッグ機能を共有することによって、アンマネージ コード デバッガーと共存できます。

また、CLR デバッグ API には、プロセスをデバッグするための 2 つのオプションがあります。

  • ソフトアタッチ オプションでは、プロセスのマネージ部分のみをデバッグします。 プロセスにソフトアタッチされたデバッガーは、後でプロセスからデタッチできます。

  • ハードアタッチ オプションでは、プロセスのマネージ部分とアンマネージ部分の両方をデバッグします。すべての Win32 デバッグ イベントは、デバッグ API を通して公開されます。

混合言語環境

コンポーネント ソフトウェアでは、各種コンポーネントが異なる言語で作成されている可能性があります。 デバッガーで言語の違いが認識されなければ、デバッガーはデータを正しい形式で表示したり、式を正しい構文で評価したりできません。

CLR にはソース言語の概念がないため、CLR デバッグ API は混合言語環境を直接サポートしていません。 デバッガーの既存のソース マップ機能に、特定の関数をその関数の実装言語に対応付ける機能が必要です。

複数プロセスと分散プログラム

コンポーネント プログラムには、異なるプロセスやネットワーク上の他のコンピューターで実行される連携コンポーネントが含まれている可能性があります。 実行されている処理の論理ビューを得るには、プロセスとコンピューターの間の実行ロジックをトレースする機能がデバッガーに必要です。

CLR デバッグ API は、複数プロセス デバッグを直接サポートしていません。 CLR デバッグ API を使用しているデバッガーには複数プロセス デバッグの直接サポート機能が必要であり、この機能がある既存のメソッドは引き続き正しく動作します。

ページのトップへ

API のカテゴリ

デバッガー API には、次の 3 つのインターフェイス グループが含まれます。通常、これらはすべて CLR デバッガーによって使用され、アンマネージ コードとして実装されます。

  • CLR アプリケーションのデバッグをサポートするインターフェイス。

  • シンボリック デバッグ情報にアクセスするためのインターフェイス。通常は、プログラム データベース (PDB: Program Database) ファイルに格納されます。

  • コンピューター上のプロセスおよびアプリケーション ドメインのクエリをサポートするインターフェイス。

デバッグ API は、次の 2 つのインターフェイス セットに依存します。

  • クラスやメソッド型の情報など、静的なプログラム情報の検査を処理するためのメタデータ API。

  • マネージ コード デバッガーのソース レベル デバッグをサポートするためのシンボル ストア API。

また、デバッグ インターフェイスは、次の表に示すような機能的なカテゴリにまとめることもできます。

API のカテゴリ

説明

登録

CLR に登録するため、および特定のイベントが発生したときの通知を要求するために、デバッガーが呼び出すインターフェイス。

通知

さまざまなイベントをデバッガーに通知するため、および要求された情報を返すために、CLR が使用するコールバック インターフェイス。 これらのインターフェイスは、デバッガーが実装する必要があります。

ブレークポイント

ブレークポイントに関する情報を取得するために、デバッガーが呼び出すインターフェイス。

実行

デバッグ対象の実行を制御するため、および呼び出し履歴にアクセスするために、デバッガーが呼び出すインターフェイス。

情報

デバッグ対象に関する情報を取得するために、デバッガーが呼び出すインターフェイス。

列挙型

オブジェクトを列挙するために、デバッガーが呼び出すインターフェイス。

変更

デバッグされているコードを変更するために、デバッガーが呼び出すインターフェイス。

以下のセクションでは、共通言語ランタイム (CLR) のデバッグ サービスによって提供される機能について説明します。

ページのトップへ

プログラムへのアタッチまたはプログラムの起動

CLR を使用すると、実行中のプログラムにデバッガーをアタッチしたり、新しいプロセスを開始したりできます。 CLR デバッグ サービスは Just-In-Time (JIT) デバッグをサポートしており、ハンドルされない例外をスローしたプログラムにデバッガーをアタッチできます。 ただし、デバッグ可能モードで実行されていないプログラムでは、使用できるデバッグ情報が少ない場合があります。 この問題を回避するには、プログラムを常にデバッグ可能なモードで実行します。 デバッグ可能モードの詳細については、次のトピックを参照してください。

ページのトップへ

実行の制御

CLR デバッグ サービスには、プログラムの実行を制御するいくつかの方法が用意されています。 これには、ブレークポイント、シングル ステップ実行、例外通知、関数の評価、およびプログラムの起動とシャットダウンに関係するその他のイベントが含まれます。

CLR デバッグ API ではマネージ コードのみの例外を制御できます。 アンマネージ コードで例外制御を実行するには、デバッガーにその機能を別途実装する必要があります。

ブレークポイント

コードを指定し、中断する位置の Miccrosoft Intermediate Language (MSIL) オフセットまたはネイティブ オフセットを指定することで、ブレークポイントを作成できます。 ブレークポイントを作成すると、ブレークポイントが検出されたときにデバッガーに通知されます。 デバッグ API は、条件付きブレークポイントを直接サポートしていません。 ただし、条件付きブレークポイントは、デバッガーがブレークポイントに応じて式を評価し、ユーザーに停止を通知するかどうかを決定することで実装できます。

ステップ実行

CLR デバッグ サービスにはさまざまなステップ実行機能が用意されています。 プログラム コードで一度に 1 つの命令だけを実行するか (シングル ステップ実行)、ある範囲の命令を一度に実行できます (範囲ステップ実行)。 関数に対するステップ オーバー、ステップ イン、またはステップ アウトを実行できます。 ステップ実行を中断させる例外が発生した場合に、CLR デバッグ サービスによってデバッガーに通知することもできます。

デバッグ サービスではアンマネージ コードのステップ実行を直接サポートはしていませんが、ステップ実行処理中にアンマネージ コードに達した場合にデバッガーに制御を渡すコールバックが用意されています。 また、アンマネージ コードからマネージ コードに入る直前の時点をデバッガーで確認できる機能も用意されています。

CLR はソースレベルのステップ実行を直接サポートしていません。 デバッガーは、範囲ステップ実行と独自のソース マッピング情報を使用することで、この機能を実装できます。 シンボル ストア インターフェイスを使用すると、ソースレベルの情報を取得できます。 これらのインターフェイスの詳細については、「シンボル ストア診断 (アンマネージ API リファレンス)」を参照してください。

例外

CLR デバッグ サービスを使用すると、マネージ コード内の初回例外とセカンド チャンス例外の両方をデバッガーに通知できます。 スローされたオブジェクトを各ポイントで検査に使用できます。

アンマネージ コード内のネイティブな例外は、マネージ コードまで反映されない限り CLR では処理されません。 ただし、CLR デバッグ サービスと共有されている Win32 デバッグ サービスを使用すると、アンマネージ例外を処理できます。

プログラム イベント

CLR デバッグ サービスにより、多数のプログラム イベントが、発生時にデバッガーに通知されます。 通知されるイベントには、プロセスの作成と終了、スレッドの作成と終了、アプリケーション ドメインの作成と終了、アセンブリの読み込みとアンロード、モジュールの読み込みとアンロード、クラスの読み込みとアンロードがあります。 パフォーマンスを維持するために、モジュールに対するクラスの読み込みとアンロードのイベントを無効にすることができます。 既定では、クラスの読み込みとアンロードのイベントは無効になっています。

スレッド コントロール

CLR デバッグ サービスには、個々の (マネージ) スレッドを保留および再開するためのインターフェイスが用意されています。

ページのトップへ

プログラムの状態の確認

CLR デバッグ サービスには、プロセスが停止状態のときに、マネージ コードを実行しているプロセスの各部分を検査する詳細な方法が用意されています。 プロセスを検査することにより、物理スレッドのリストを取得できます。

スレッドを調査することにより、呼び出し履歴を検査できます。 スレッドの呼び出し履歴は、チェーン レベルとスタック フレーム レベルの 2 つのレベルに分解されます。 呼び出し履歴はまずチェーンに分解されます。 チェーンは、連続する呼び出し履歴の論理セグメントです。 チェーンには、マネージ スタック フレームまたはアンマネージ スタック フレームのいずれかが含まれています (両方が含まれていることはありません)。 さらに、単一のチェーンに含まれるすべてのマネージ コール フレームは同じ CLR コンテキストを共有します。 チェーンはマネージまたはアンマネージのどちらでもかまいません。

各マネージ チェーンは、さらに単一のスタック フレームに分解されます。 各スタック フレームは 1 回のメソッド呼び出しを表します。 スタック フレームに照会して、実行中のコードを取得できます。または、実行中のコードの引数、ローカル変数、およびネイティブ レジスタを取得できます。

アンマネージ チェーンにスタック フレームは含まれません。 代わりに、アンマネージ チェーンは、アンマネージ コードに割り当てられているスタック アドレスの範囲を提供します。 アンマネージ コード デバッガーは、スタックのアンマネージ部分のデコードとスタック トレースを行うかどうかを決定できます。

メモメモ

CLR デバッグ サービスは、ソース コードに含まれるローカル変数の概念をサポートしません。デバッガーはローカル変数を割り当てにマップするかどうかを決定できます。

CLR デバッグ サービスでは、グローバル変数、クラス静的変数、およびスレッド ローカル変数にアクセスすることもできます。

ページのトップへ

プログラムの状態の変更

CLR デバッグ サービスにより、デバッガーは実行中に命令ポインターの物理位置を変更できます。ただし、これは危険を伴う操作です。 次の条件が満たされている場合は、命令ポインターを正常に変更できる可能性があります。

  • 現在の命令ポインターとターゲットの命令ポインターが両方ともシーケンス ポイントにある。 シーケンス ポイントはおよそのステートメント境界を表します。

  • ターゲット命令ポインターが例外フィルター、catch ブロック、または finally ブロック内にない。

  • 現在の命令ポインターが catch ブロック内にあり、ターゲット命令ポインターが catch ブロックの外側にない。

  • ターゲット命令ポインターが現在の命令ポインターと同じフレーム内にある。

命令ポインターの物理位置が変更されると、現在の命令ポインターの位置にある変数が、ターゲット命令ポインターの位置にある変数にマップされます。 ターゲット命令ポインターの位置にあるガベージ コレクション参照は、正しく初期化されます。

命令ポインターが変更された後、CLR デバッグ サービスはキャッシュされたスタック情報を無効とマークし、次回それが必要になったときに情報を更新します。 フレームやチェーンなどのスタック情報へのポインターをキャッシュするデバッガーは、命令ポインターを変更した後、この情報を更新する必要があります。

デバッガーは、プログラムが停止しているときにプログラムのデータを変更することもできます。 デバッガーは検査と同様の方法で、関数の実行中に関数のローカル変数と引数を変更できます。 また、配列およびオブジェクトのフィールドと、静的フィールドおよびグローバル変数を更新できます。

ページのトップへ

エディット コンティニュの使用

エディット コンティニュ機能を使用すると、デバッグ セッション中に次の操作を実行できます。

  • ソース コードを編集する。

  • 変更したソースを再コンパイルする。

  • デバッグ中である実行可能ファイルの残りの部分の実行時状態を保持する。

  • 実行可能ファイルを最初から再実行せずにデバッグ セッションを続行する。

ページのトップへ

関数の評価

ユーザー式とオブジェクトの動的なプロパティを評価するには、デバッグ対象プロセスのコードを実行するための方法がデバッガーに必要です。 CLR デバッグ サービスを使用すると、デバッガーは関数またはメソッドを呼び出して、デバッガーのプロセスの内部で実行できます。

このような処理はリスクを伴うため (たとえば、既存のコードにデッドロックが発生することがあります)、CLR を使用することで、デバッガーはこのような処理を中止できます。 評価が正常に中止されると、スレッドは、評価が行われなかった場合と同様に処理されます。ただし、例外として、部分的な評価によるローカル変数への副作用があります。 関数からアンマネージ コードまたはアンマネージ ブロックに何らかの方法で呼び出しが行われると、評価を終了できない場合があります。

関数の評価が完了すると、CLR はコールバックを使用して、評価が正常に終了したか、関数が例外をスローしたかをデバッガーに通知します。 ICorDebugValue メソッドおよび ICorDebugValue2 メソッドを使用して、評価の結果を検査できます。

関数の評価が実行されるスレッドは、マネージ コード内の、ガベージ コレクションに対して安全なポイントで停止する必要があります (関数の評価はハンドルされない例外に対しても実行できます)。 最適化されていないコードでは、このようなセーフ ポイントはどこにでもあります。ブレークポイントまたは MSIL レベルのステップ処理のほとんどがセーフ ポイントで完了します。 ただし、このようなポイントは、最適化されたコードにはほとんどありません。 関数全体でセーフ ポイントが 1 つもない場合もあります。 ガベージ コレクションに対して安全なポイントが出現する頻度は、関数によって異なります。 最適化されていないコード内でも、セーフ ポイントで停止しないこともできます。 最適化されたコードでも最適化されていないコードでも、ICorDebugController::Stop メソッドがセーフ ポイントで実行されることはほとんどありません。

CLR デバッグ サービスはスレッドに新しいチェーンを設定して関数の評価を開始し、要求された関数を呼び出します。 評価が開始するとすぐに、実行制御、検査、関数の評価などのデバッグ API のすべての機能が使用できるようになります。 入れ子の評価はサポートされています。ブレークポイントは通常どおり処理されます。

ページのトップへ

コードの動的な挿入

一部のデバッガーでは、[イミディエイト] ウィンドウに任意のステートメントを入力し、入力したステートメントを実行できます。 CLR デバッグ サービスはこのシナリオをサポートします。 妥当な範囲内で、どのようなコードを動的に挿入できるかについての制限はありません (たとえば、ローカルでない goto ステートメントは使用できません)。

動的なコード挿入は、エディット コンティニュ操作と関数の評価を組み合わせて実装されています。 挿入するコードは関数内にラップされ、エディット コンティニュを使用して挿入されます。 その後、挿入された関数が評価されます。 必要に応じて、ByRef 引数をラッパー関数に渡して、副作用を即時かつ永続的にすることができます。

ページのトップへ

サポートされる環境

CLR のデバッグ機能は、CLR がサポートするすべてのプロセッサとオペレーティング システムで利用できますが、次のような例外があります。

  • 64 ビット オペレーティング システムでは、エディット コンティニュおよび混合モード デバッグはサポートされません。 SetIP メソッド (ICorDebugILFrame::SetIP および ICorDebugNativeFrame::SetIP) では、64 ビット オペレーティング システムに固有の制限事項があります。 他の機能はすべてのプロセッサで同じです。ただし、ポインター サイズやレジスタ コンテキストなどのプロセッサ固有のデータ表現はあります。

  • Win9x ベースのオペレーティング システムでは、エディット コンティニュおよび混合モード デバッグはサポートされません。 他の機能はすべてのオペレーティング システムで同じです。 ただし、特定の例外がいくつかあります。これらについては、個々の関数のマニュアルで説明されています。

ページのトップへ

関連トピック

タイトル

説明

CLR デバッグのアーキテクチャ

CLR デバッグ API の各種コンポーネントが CLR およびデバッガーとやり取りする方法について説明します。

.NET Framework 2.0 でのデバッグ API の変更点

.NET Framework Version 2.0 でのデバッグに関する変更と機能強化について説明します。

CorDebug.idl インターフェイスの実行前の状態

一部の CLR デバッグ インターフェイスではデバッグ対象のプロセスを特定の状態にする必要があることについて説明します。

ランタイム プロセスのデバッグ

ランタイム プロセスをデバッグする方法について、順をおって説明します。

デバッグ中のプログラムの制御

デバッガーで CLR デバッグ API を使用してブレークポイントを設定する方法、マネージ コードおよびアンマネージ コードをステップ実行する方法、および例外を処理する方法について説明します。

デバッグ中のプログラムの調査

デバッガーで CLR デバッグ API を使用してマネージ スタック フレームにアクセスする方法、および式を評価する方法について説明します。

デバッグ API によるコードの動的な挿入

動的コード挿入について説明します。動的コード挿入では、CLR がアクティブなスレッドをハイジャックし、元の移植可能な実行可能 (PE: Portable Executable) ファイルに存在しないコードを実行します。

デバッグ API での発行プロセス

CLR のプロセス発行インターフェイスの概要について説明します。CLR のプロセス発行プロセスは、コンピューター上のプロセスとアプリケーション ドメインに関する情報を列挙し、提供します。

デバッグ API に関するセキュリティ上の考慮事項

CLR デバッグ API の使用に関するセキュリティ上の考慮事項について説明します。

デバッグ コクラス

デバッグ API が使用するアンマネージ コクラスについて説明します。

デバッグのインターフェイス

共通言語ランタイムで実行するプログラムのデバッグを処理するアンマネージ インターフェイスについて説明します。

デバッグ グローバル静的関数

デバッグ API が使用するアンマネージ グローバル静的関数について説明します。

列挙体のデバッグ

デバッグ API が使用するアンマネージ列挙体について説明します。

デバッグ構造体

デバッグ API で使用されるアンマネージ構造体について説明します。

ページのトップへ