try-finally ステートメントは、C および C++ 言語での構造化例外処理をサポートする Microsoft 固有の拡張機能です。
構文
次の構文では、 try-finally ステートメントについて説明します。
// . . .
__try {
// guarded code
}
__finally {
// termination code
}
// . . .
構文
try-finally-statement:
__trycompound-statement__finallycompound-statement
try-finally ステートメントは、C および C++ 言語に対する Microsoft の拡張機能であり、コード ブロックの実行が中断されたときに、ターゲット アプリケーションがクリーンアップ コードの実行を保証できるようにします。 クリーンアップは、メモリの割り当て解除、ファイルの終了、ファイル ハンドルの解放などのタスクで構成されます。
try-finally ステートメントは、ルーチンから早期に戻る可能性があるエラーのチェックが行われる場所が複数あるルーチンに特に役立ちます。
関連情報とコード サンプルについては、「 try-except ステートメント」を参照してください。 一般的な構造化例外処理の詳細については、「 構造化例外処理」を参照してください。 C++/CLI を使用したマネージド アプリケーションでの例外処理の詳細については、「/clrの例外処理」を参照してください。
注
構造化例外処理は、C と C++ の両方のソース ファイルに対して Win32 で動作します。 ただし、C++ 用に特別に設計されているわけではありません。 C++ 例外処理を使用して、コードの移植性を高めることができます。 また、C++ 例外処理は、任意の型の例外を処理できる点で柔軟性が高くなります。 C++ プログラムの場合は、C++ 例外処理メカニズム (try、 catch、および throw ステートメント) を使用することをお勧めします。
__try句の後の複合ステートメントは、保護されたセクションです。
__finally句の後の複合ステートメントが終了ハンドラーです。 ハンドラーは、保護されたセクションが終了したときに実行される一連のアクションを指定します。これは、保護されたセクションを例外 (異常終了) によって終了するか、標準のフォールスルー (通常終了) によって終了するかに関係なく指定します。
制御は、単純な順次実行 (フォールスルー) によって __try ステートメントに到達します。 コントロールが __tryに入ると、関連付けられているハンドラーがアクティブになります。 制御のフローが try ブロックの最後に達すると、次のように実行が続行されます。
終了ハンドラーが呼び出されます。
終了ハンドラーが完了すると、
__finallyステートメントの後に実行が続行されます。 ただし、保護されたセクションは終了します (たとえば、保護された本体からgotoを介して、またはreturnステートメントを使用して)、制御フローが保護されたセクションから移動する 前に 終了ハンドラーが実行されます。__finallyステートメントは、適切な例外ハンドラーの検索をブロックしません。
__try ブロックで例外が発生した場合、オペレーティング システムは例外のハンドラーを見つける必要があります。そうしないと、プログラムが失敗します。 ハンドラーが見つかった場合、すべての __finally ブロックが実行され、ハンドラーで実行が再開されます。
たとえば、次の図に示すように、関数 A を関数 D にリンクする一連の関数呼び出しがあるとします。 各関数には、1 つの終了ハンドラーがあります。 例外が関数 D で発生し、A で処理された場合、終了ハンドラーは、システムがスタックをアンワインドすると、次の順序で呼び出されます: D、C、B。
この図は、関数 B を呼び出す関数 A から始まり、関数 C を呼び出し、関数 D を呼び出します。関数 D は例外を発生させます。 終了ハンドラーは、次の順序で呼び出されます。D の終了ハンドラー、次に C、B、A が例外を処理します。
終了ハンドラーの実行順序
注
try-finally の動作は、C# など、 finallyの使用をサポートする他の言語とは異なります。 1 つの __try は、 __finally と __exceptの両方を持つ場合がありますが、両方を持つわけではありません。 両方を一緒に使用する場合は、外側の try-except ステートメントで内部 try-finally ステートメントを囲む必要があります。 各ブロックの実行タイミングを指定する規則も異なります。
以前のバージョンとの互換性のために、コンパイラ オプション /Za(言語拡張機能を無効にする) が指定されていない限り、_try、_finally、および_leaveは__try、__finally、および__leaveのシノニムです。
__leave キーワード
__leave キーワードは、try-finally ステートメントの保護されたセクション内でのみ有効であり、その効果は保護されたセクションの末尾にジャンプすることです。 実行は、終了ハンドラーの最初のステートメントで続行されます。
gotoステートメントは保護されたセクションから飛び出すこともできますが、スタック アンワインドを呼び出すのでパフォーマンスが低下します。
__leave ステートメントはスタック アンワインドを引き起こさないので、より効率的です。
異常終了
longjmp ランタイム関数を使用して try-finally ステートメントを終了すると、異常終了と見なされます。
__tryステートメントに飛び込むのは適していませんが、1 つから飛び出すのは有効です。 出発地 (__try ブロックの正常終了) と宛先 (例外を処理する__except ブロック) の間でアクティブになっているすべての__finallyステートメントを実行する必要があります。 ローカル アンワインドと呼ばれます。
ブロックからのジャンプを含め、何らかの理由で __try ブロックが途中で終了した場合、システムは、スタックをアンワインドするプロセスの一部として、関連付けられている __finally ブロックを実行します。 このような場合、AbnormalTermination関数は、__finally ブロック内から呼び出された場合はtrueを返します。それ以外の場合は、falseを返します。
try-finally ステートメントの実行中にプロセスが強制終了された場合、終了ハンドラーは呼び出されません。
END Microsoft 固有