Microsoft Windowsファミリのオペレーティング システムでは、いくつかの特定の例外処理メカニズムが採用されています。
Microsoft構造化例外処理は、Windowsのネイティブ例外処理メカニズムであり、ベクトル化例外処理(VEH)[1]finallyの先駆けとなる技術です。標準C++例外処理には存在しないメカニズム(ただし、後に導入されるほとんどの命令型言語には存在します)を備えています。SEHは実行スレッドごとに個別に設定および処理されます。
Microsoftは、SEHをコンパイラレベルでのみプログラミング手法としてサポートしています。MS Visual C++コンパイラには、この目的のために、__try、__except、__finally— という3つの非標準キーワードが用意されています。その他の例外処理は、例えばSEH例外を手動で発生させるためのWin32 API関数[2]RaiseExceptionなどによってサポートされています。
int filterExpression ( EXCEPTION_POINTERS * ep ) { ep -> ContextRecord -> Eip += 8 ; // 除算命令は2~8バイトでエンコードされる可能性がありますreturn EXCEPTION_CONTINUE_EXECUTION ; }
int main ( void ) { static int zero = 0 ; __try { zero = 1 / zero ; asm { nop nop nop nop nop nop nop nop } printf ( "例外を過ぎました。\n " ); } __except ( filterExpression ( GetExceptionInformation ())) { printf ( "ハンドラーが呼び出されました。\n " ); } return 0 ; }
Windows IA-32エディションまたはx86-64バージョンのWoW64エミュレーション レイヤーの各実行スレッドには、スレッド情報ブロックの先頭に、ドキュメント化されていない_EXCEPTION_REGISTRATION_RECORDリストへのリンクがあります。文は基本的にコンパイラ定義の関数を呼び出します。その関数は、スタック上に[a] の関数を指す_EXCEPTION_REGISTRATION_RECORDを割り当て、[b]レコードをリストの先頭に追加します。ブロックの最後では、逆の操作を行うコンパイラ定義の関数が呼び出されます。これらのコンパイラ定義のルーチンはどちらもインライン にすることができます。プログラマ定義のブロックとブロックはすべて、 内から呼び出されます。プログラマ定義のブロックが存在する場合、によって作成された_EXCEPTION_REGISTRATION_RECORDは、によって使用されるいくつかの追加フィールドで拡張されます。[3] __tryEH_prolog __except_handler3msvcrt.dll__try EH_epilog__except__finally__except_handler3EH_prolog__except_handler3
ユーザーモードコードで例外が発生した場合、オペレーティングシステムは[c] 、スレッドの_EXCEPTION_REGISTRATION_RECORDリストを解析し、各例外ハンドラを順番に呼び出します。これは、ハンドラが例外処理を完了したことを示す(戻り値によって)か、リストの最後まで呼び出されるまで続きます。リストの最後は常に[d]であり、一般保護違反エラーメッセージが表示されます。その後、リストがもう一度走査され、ハンドラは使用されたリソースをクリーンアップする機会を得ます。最後に、実行はカーネルモード[e]に戻り、プロセスは再開または終了します。
kernel32!UnhandledExceptionFilter
このモードの SEH に関する特許 (US5628016) は 2014 年に失効しました。
64ビットWindowsのSEHは、実行時例外ハンドラリストを必要としません。代わりに、例外発生時にシステムによって解釈されるスタックアンワインドテーブル( )を使用します。 [4] [5]
つまり、コンパイラは手動でスタックアンワインドを実行し、例外ハンドラを適切に呼び出すための追加コードを生成する必要がありません。コンパイラは、スタックフレームのレイアウトと指定された例外ハンドラに関する情報を、アンワインドテーブルの形式で出力するだけで済みます。
UNWIND_INFO
Mingw-w64のGCC 4.8+は、C++例外に64ビットSEHの使用をサポートしています。LLVM clangはx86とx64の両方でサポートしています。__try [ 6]
ベクトル例外処理はWindows XPで導入されました。[7]ベクトル例外処理は、C++やVisual Basicなどの言語を使用するWindowsプログラマーに提供されています。VEHは構造化例外処理(SEH)に取って代わるものではなく、VEHとSEHは共存し、VEHハンドラーはSEHハンドラーよりも優先されます。[1] [7] SEHと比較すると、VEHはカーネルから配信されるUnixシグナル のように動作します。[8]
ntdll.dllおよびkernel32.dll、VCランタイムに静的にリンクされた他のプログラムでは、代わりにこの関数がコンパイルされている。
ntdll!RtlDispatchExceptionシステム ルーチンから呼び出され、ntdll!KiUserExceptionDispatcherそのシステム ルーチンがカーネル関数から呼び出されますnt!KiDispatchException。( Ken Johnson (2007 年 11 月 16 日) を参照してください。「NTDLL カーネル モードからユーザー モードへのコールバックのカタログ、パート 2: KiUserExceptionDispatcher」)。詳細は
ntdll!KiUserExceptionDispatcherいずれかを呼び出しますnt!ZwContinuent!ZwRaiseException
/link /safeseh:no。