次の例では、例外ハンドラーの使用方法を示します。
一部の例では、__except フィルター式内で GetExceptionCode 関数を使用して、ハンドラーを実行する前に例外の種類を確認します。 これにより、システムは、他の種類の例外が発生した場合に、適切なハンドラーの検索を続行できます。
一般に、例外の種類が予期され、エラーが発生しているアドレスがわかっている場合にのみ、例外フィルターからEXCEPTION_EXECUTE_HANDLERを返します。 既定の例外ハンドラーで、予期しない例外の種類とエラーが発生しているアドレスを処理することを許可する必要があります。
例 1
次のコード フラグメントでは、構造化例外処理を使用して、2 つの 32 ビット整数に対する除算演算で 0 除算エラーが発生するかどうかを確認します。 この場合、関数は FALSE を返します。それ以外の場合は TRUE を返します。
BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
return FALSE;
}
return TRUE;
}
例 2
次の例の関数は 、DebugBreak 関数を呼び出し、構造化例外処理を使用してブレークポイント例外をチェックします。 発生した場合は、例外がデバッガーによって処理されなかったことを意味し、関数は FALSE を返します。それ以外の場合は TRUE を返します。
BOOL CheckForDebugger()
{
__try
{
DebugBreak();
}
__except(GetExceptionCode() == EXCEPTION_BREAKPOINT ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// No debugger is attached, so return FALSE
// and continue.
return FALSE;
}
return TRUE;
}
例 3
次の例は、入れ子になったハンドラーの相互作用を示しています。 RaiseException 関数は、例外ハンドラーの保護されたコードブロック内にある終了ハンドラーの保護されたコードブロックで例外を発生します。 この例外により、システムは FilterFunction 関数を評価し、その戻り値によって例外ハンドラーが呼び出されます。 ただし、例外ハンドラー ブロックが実行される前に、制御フローが終了ハンドラーの __try ブロックを残しているため、終了ハンドラーの __finally ブロックが実行されます。
DWORD FilterFunction()
{
printf("1 "); // printed first
return EXCEPTION_EXECUTE_HANDLER;
}
VOID main(VOID)
{
__try
{
__try
{
RaiseException(
1, // exception code
0, // continuable exception
0, NULL); // no arguments
}
__finally
{
printf("2 "); // this is printed second
}
}
__except ( FilterFunction() )
{
printf("3\n"); // this is printed last
}
}