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