終了ハンドラー構文
__try キーワードと __finally キーワードは、終了ハンドラーを構築するために使用されます。 次の例は、終了ハンドラーの構造を示しています。
__try
{
// guarded body of code
}
__finally
{
// __finally block
}
例については、「終了ハンドラーの使用」を参照してください。
例外ハンドラーと同様に、__try ブロックと __finally ブロックの両方に中かっこ ({}) が必要です。また、goto ステートメントを使用していずれかのブロックにジャンプすることはできません。
__try ブロックには、終了ハンドラーによって保護されているコードの保護された本文が含まれています。 関数には任意の数の終了ハンドラーを含めることができ、これらの終了処理ブロックは同じ関数内または異なる関数内にネストできます。
__finally ブロックは、制御フローが __try ブロックを離れるたびに実行されます。 ただし、__try ブロック内で ExitProcess、ExitThread、または abort のいずれかの関数を呼び出した場合、__finally ブロックは実行されません。
__finally ブロックは、終了ハンドラーが配置されている関数のコンテキストで実行されます。 つまり、__finally ブロックはその関数のローカル変数にアクセスできます。 __finally ブロックの実行は、次のいずれかの方法で終了できます。
- ブロック内の最後のステートメントの実行と次の命令への継続
- 制御ステートメント (return、break、continue、または goto) の使用
- longjmp または例外ハンドラーへのジャンプの使用
フレーム ベースの例外ハンドラーの例外処理ブロックを呼び出す例外が原因で __try ブロックの実行が終了した場合、__finally ブロックは例外処理ブロックが実行される前に実行されます。 同様に、__try ブロックから longjmp ランタイム ライブラリ関数を呼び出すと、longjmp 操作のターゲットで実行が再開される前に、__finally ブロックが実行されます。 制御ステートメント (return、break、continue、または goto) によって __try ブロックの実行が終了すると、__finally ブロックが実行されます。
AbnormalTermination 関数は、__finally ブロック内で、__try ブロックが順番に終了したかどうか、つまり、閉じかっこ (}) に達したかどうかを判断するために使用できます。 longjmp の呼び出し、例外ハンドラーへのジャンプ、または return、break、continue、または goto ステートメントのために、__try ブロックを離れると、異常終了と見なされます。 順番に終了しないと、システムはすべてのスタック フレームを逆の順序で検索して、終了ハンドラーを呼び出す必要があるかどうかを判断することに注意してください。 これにより、数百の命令が実行されるため、パフォーマンスが低下する可能性があります。
終了ハンドラーの異常終了を回避するには、実行をブロックの最後まで続行する必要があります。 __leave ステートメントを実行することもできます。 __leave ステートメントを使用すると、異常終了とそのパフォーマンスの低下を引き起こすことなく、__try ブロックを即時に終了できます。 コンパイラのドキュメントを調べて、__leave ステートメントがサポートされているかどうかを確認します。
return 制御ステートメントの戻り値が原因で __finally ブロックの実行が終了した場合は、外側の関数の右中かっこへの goto と同じになります。 したがって、外側の関数は返されます。