例外処理
オペレーティング システムは、構造化例外処理を使用して、特定の種類のエラーを通知します。 ドライバーによって呼び出されたルーチンは、ドライバーが処理する必要がある例外を発生させることができます。
システムは、次の一般的な種類の例外をトラップします。
ハードウェアによって定義された障害またはトラップ。例:
- アクセス違反 (以下を参照)
- データ型の不整合 (奇数バイト境界に整合された 16 ビット エンティティなど)
- 不正な特権命令
- 無効なロック シーケンス (コードのインターロックされたセクション内で無効な一連の命令を実行しようとした)
- 整数を 0 で除算し、オーバーフローする
- 浮動小数点は、ゼロ、オーバーフロー、アンダーフロー、予約オペランドで除算される
- ブレークポイントと単一ステップの実行 (デバッガーをサポートするため)
システム ソフトウェア定義の例外。例:
- ガード ページ違反 (ガード ページ内の場所に対してデータの読み込みまたは格納を試みる)
- ページ読み取りエラー (メモリへのページの読み取りを試み、同時 I/O エラーが発生)
アクセス違反とは、現在のページ保護設定では許可されていないページに対して操作を実行しようとすることです。 アクセス違反は、以下の状況で発生します。
読み取り専用ページへの書き込みなど、無効な読み取りまたは書き込み操作。
現在のプログラムのアドレス空間の制限を超えてメモリにアクセスするため (長さの違反と呼ばれます)。
現在常駐しているが、システム コンポーネントの使用専用のページにアクセスするため。 たとえば、ユーザー モード コードでは、カーネルが使用しているページへのアクセスは許可されません。
操作によって例外が発生する可能性がある場合、ドライバーは操作を try/except ブロックで囲む必要があります。 ユーザー モードでの場所へのアクセスは、例外の一般的な原因です。 たとえば、ProbeForWrite ルーチンは、ドライバーが実際にユーザー モード バッファーに書き込むことができることをチェックします。 できない場合、ルーチンは STATUS_ACCESS_VIOLATION 例外を発生させます。 次のコード例では、ドライバーは try/except で ProbeForWrite を呼び出し、結果の例外が発生した場合にそれを処理できるようにします。
try {
...
ProbeForWrite(Buffer, BufferSize, BufferAlignment);
/* Note that any access (not just the probe, which must come first,
* by the way) to Buffer must also be within a try-except.
*/
...
} except (EXCEPTION_EXECUTE_HANDLER) {
/* Error handling code */
...
}
ドライバーは、発生した例外を処理する必要があります。 処理されない例外により、システムはバグ チェックを行います。 例外を発生させるドライバーは、その例外を処理する必要があります。下位レベルのドライバーは、例外を処理するためにより上位レベルのドライバーに依存することはできません。
ドライバーは、ExRaiseAccessViolation、ExRaiseDatatypeMisalignment、または ExRaiseStatus ルーチンを使用して、例外を直接発生させることができます。 ドライバーは、これらのルーチンが発生したすべての例外を処理する必要があります。
少なくとも特定の状況で例外が発生する可能性があるルーチンの一部を以下に示します。
ユーザー モード バッファーへのメモリ アクセスによっても、アクセス違反が発生する可能性があります。 詳細については、「ユーザー空間アドレスを参照する際のエラー」を参照してください。
構造化例外処理は、C++ 例外とは異なる点に注意してください。 カーネルは C++ 例外をサポートしていません。
構造化例外処理について詳しくは、Microsoft Windows SDK と Visual Studio のドキュメントをご覧ください。