例外フィルターの記述

例外は、例外ハンドラーのレベルにジャンプするか、実行を続けるかのいずれかにより、処理できます。 例外ハンドラー コードを使って例外を処理し、フォール スルーするのではなく、"フィルター" 式を使って問題を解消することができます。 その後、EXCEPTION_CONTINUE_EXECUTION (-1) を返すことで、スタックをクリアすることなく、通常のフローを再開できます。

Note

一部の例外は、続行できない場合があります。 このような例外で "フィルター" が -1 に評価されると、新しい例外が発生します。 RaiseException を呼び出すときに、例外を続行するかどうかを指定します。

たとえば、次のコードでは、"フィルター" 式で関数呼び出しを使用します。この関数では、問題を処理し、-1 を返して通常の制御フローを再開します。

// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int main() {
   int Eval_Exception( int );

   __try {}

   __except ( Eval_Exception( GetExceptionCode( ))) {
      ;
   }

}
void ResetVars( int ) {}
int Eval_Exception ( int n_except ) {
   if ( n_except != STATUS_INTEGER_OVERFLOW &&
      n_except != STATUS_FLOAT_OVERFLOW )   // Pass on most exceptions
   return EXCEPTION_CONTINUE_SEARCH;

   // Execute some code to clean up problem
   ResetVars( 0 );   // initializes data to 0
   return EXCEPTION_CONTINUE_EXECUTION;
}

"フィルター" で複雑な処理を実行する場合は、"フィルター" 式で関数呼び出しを使用することをお勧めします。 式を評価すると、関数 (この場合、Eval_Exception) が実行されます。

GetExceptionCode を使って例外を判断していることに注意してください。 この関数は、__except ステートメントのフィルター式の内部で呼び出す必要があります。 Eval_Exception から GetExceptionCode を呼び出すことはできませんが、例外コードを渡す必要があります。

このハンドラーは、例外が整数または浮動小数点数のオーバーフローでなければ、他のハンドラーに制御を渡します。 オーバーフローがあった場合、ハンドラーは関数 (ResetVars は一例で、API 関数ではありません) を呼び出して、いくつかのグローバル関数をリセットします。 この例では __except ステートメント ブロックは空ですが、Eval_ExceptionEXCEPTION_EXECUTE_HANDLER (1) を返すことはないため、実行できません。

関数呼び出しの使用は、複雑なフィルター式を処理するための優れた汎用的手法です。 その他の便利な 2 つの C 言語機能を次に示します。

  • 条件演算子

  • コンマ演算子

この場合に条件演算子が役立つことがよくあります。 特定のリターン コードを確認し、2 つの異なる値のうちの 1 つを返すために使用できます。 たとえば、次のコードのフィルターは、例外が STATUS_INTEGER_OVERFLOW である場合にのみ例外を認識します。

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ? 1 : 0 ) {

次のコードでは同じ結果が生成されるため、ここでは条件演算子が主として明確さを高めるために使用されています。

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ) {

条件演算子は、フィルターが -1 (EXCEPTION_CONTINUE_EXECUTION) と評価される必要があるような状況で役立ちます。

コンマ演算子を使うと、複数の式を順番に実行できます。 次に、最後に実行された式の値を返します。 たとえば、次のコードでは、変数に例外コードを保存してから、そのコードをテストしています。

__except( nCode = GetExceptionCode(), nCode == STATUS_INTEGER_OVERFLOW )

関連項目

例外ハンドラーの記述
Structured Exception Handling (C/C++)