Windowsでは、例外はプログラムの実行中に発生するイベントです。例外には、ハードウェア例外とソフトウェア例外の2種類があります。ハードウェア例外は、Oracle SolarisおよびLinuxオペレーティング・システム上のSIGSEGV
やSIGKILL
などのシグナルに相当します。ソフトウェア例外は、アプリケーションまたはオペレーティング・システムがRaiseException()
APIを使用して明示的に発行します。
Windowsでは、ハードウェア例外とソフトウェア例外の両方を処理するメカニズムを構造化例外処理(SEH)と呼びます。これは、C++やJavaの例外処理メカニズムに似たスタック・フレームベースの例外処理です。C++では、例7-1のように、__try
および__except
キーワードを使用して、例外が発生する可能性があるコードのセクションを保護します。
例7-1 TryおよびExceptブロック
__try {
// guarded body of code
} __except (filter-expression) {
// exception-handler block
}
__except
ブロックは、GetExceptionCode()
APIから返される整数例外コード、またはGetExceptionInformation()
APIから返される例外情報、あるいはその両方を使用するフィルタ式によってフィルタ処理されます。
このフィルタ式は、次のいずれかの値として評価されるはずです。
EXCEPTION_CONTINUE_EXECUTION = -1
このフィルタ式によって状況が修復され、例外が発生した場所から実行が継続されます。一部の例外スキームと異なり、SEHは再開モデルもサポートします。これは、シグナル・ハンドラの完了後にプログラムが中断した場所から実行が継続するという点で、Unixのシグナル処理とよく似ています。違いは、この場合のハンドラがフィルタ式だけであり、__except
ブロックではないことです。ただし、フィルタ式に関数呼出しを含めることもできます。
EXCEPTION_CONTINUE_SEARCH = 0
現在のハンドラはこの例外を処理できません。次のハンドラのハンドラ検索が続行されます。これは、C++およびJavaで例外型を照合しないcatch
ブロックに似ています。
EXCEPTION_EXECUTE_HANDLER = 1
現在のハンドラはこの例外を照合し、処理できます。__except
ブロックが実行されます。
終了ハンドラを構築するには、例7-2のように、 __try
および__finally
キーワードを使用します。
(例外のあと、または例外なしで) __try
ブロックに制御が残ったときは、__finally
ブロックが実行されます。__finally
ブロックの内部でAbnormalTermination()
APIを呼び出すと、例外のあとで制御が継続したかどうかをテストできます。
Windowsプログラムは、最上位の未処理例外フィルタ関数をインストールして、__try
/__except
ブロックで処理されない例外をキャッチすることもできます。この関数は、SetUnhandledExceptionFilter()
APIを使用してプロセス単位でインストールされます。ある例外のハンドラが存在しない場合は、UnhandledExceptionFilter()
が呼び出され、これが最上位の未処理例外フィルタ関数を(あれば)呼び出して、その例外をキャッチします。この関数によって、未処理例外をユーザーに通知するメッセージ・ボックスも表示されます。
Windowsの例外は、現在の実行ストリームに起因するUnixの同期シグナルに相当します。Windowsでは、コンソール・イベント(たとえば、ユーザーがコンソールで[Ctrl]+[C]を押した場合)などの非同期イベントは、SetConsoleCtlHandler()
APIを使用して登録されたコンソール制御ハンドラによって処理されます。
Windows上でアプリケーションがsignal()
APIを使用すると、C実行時ライブラリ(CRT)はWindowsの例外とコンソール・イベントの両方を適切なシグナルまたはC実行時エラーにマップします。たとえば、CRTは[Ctrl]+[C]をSIGINT
にマップし、他のすべてのコンソール・イベントをSIGBREAK
にマップします。同様に、SIGSEGV
ハンドラを登録すると、CRTは対応する例外をシグナルに変換します。CRTの起動コードは、main()
関数の周囲に__try
/__except
ブロックを実装しています。CRTの例外フィルタ関数(名前は_XcptFilter
)は、Win32例外をシグナルにマップし、シグナルを適切なハンドラにディスパッチします。シグナルのハンドラをSIG_DFL
(デフォルトの処理)に設定すると、_XcptFilter
はUnhandledExceptionFilter
を呼び出します。
Windows XPまたはWindows 2003では、ベクトル化例外処理メカニズムを使用することもできます。ベクトル化ハンドラは、フレームベースのハンドラではありません。プログラムは、AddVectoredExceptionHandler
APIを使用して0個以上のベクトル化例外ハンドラを登録できます。ベクトル化ハンドラは、構造化例外ハンドラ(あれば)の前に呼び出され、例外の発生場所に関係なく呼び出されます。
ベクトル化例外ハンドラは、次のいずれかの値を返します。
EXCEPTION_CONTINUE_EXECUTION
: 次のベクトル化およびSEHハンドラをスキップします。
EXCEPTION_CONTINUE_SEARCH
: 次のベクトル化またはSEHハンドラを続行します。
Windowsの例外処理の詳細は、MicrosoftのWebサイト siteを参照してください。