try-finally
明細書
try-finally
ステートメントは、C と C++ 言語での構造化例外処理をサポートする Microsoft 固有の拡張機能です。
構文
次の構文は、try-finally
ステートメントを示しています。
// . . .
__try {
// guarded code
}
__finally {
// termination code
}
// . . .
構文
try-finally-statement
=
__try
compound-statement
__finally
compound-statement
try-finally
ステートメントは C および C++ 言語に対する Microsoft の拡張機能であり、コードのブロックの実行が中断されたときに、ターゲット アプリケーションがクリーンアップ コードの実行を保証できるようにします。 クリーンアップは、メモリを解放する、ファイルを閉じる、ファイル ハンドルを解放するなどのタスクで構成されます。 try-finally
ステートメントは、ルーチンからの不完全な戻りが発生する可能性のあるエラーを複数の場所でチェックするルーチンに特に便利です。
関連情報とコード例については、「try-except
ステートメント」を参照してください。 一般的な構造化例外処理の詳細については、「構造化例外処理」を参照してください。 C++/CLI を使用したマネージド アプリケーションでの例外処理の詳細については、/clr
での例外処理に関する記事を参照してください。
Note
構造化例外処理では、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 の順に呼び出されます。
このダイアグラムは関数 A から始まり、関数 B を呼び出し、関数 C を呼び出し、関数 D を呼び出します。関数 D は例外を発生させます。 終了ハンドラーは次の順序で呼び出されます。D の終了ハンドラー、次に C、次に B、次に A が例外を処理します。
終了ハンドラー実行順序
Note
try-finally の動作は、finally
の使用をサポートする C# のような言語とは異なります。 1 つの __try
には、__finally
と __except
のいずれか、または両方がある場合があります。 両方を一緒に使用する場合は、外側の try-except ステートメントで内側の try-finally ステートメントを囲む必要があります。 各ブロックがいつ実行されるかを指定する規則も異なります。
以前のバージョンとの互換性を確保するため、_try
、_finally
、_leave
は、コンパイラ オプション /Za
(言語拡張機能の無効化) が指定されていない限り、__try
、__finally
、__leave
の同意語です。
__leave キーワード
__leave
キーワードは、try-finally
ステートメントの保護されたセクション内でのみ有効であり、その効果は保護されたセクションの末尾に移動することです。 実行は、終了ハンドラーの最初のステートメントに移って続行されます。
goto
ステートメントは、保護されたセクションの外部にジャンプすることもできますが、スタック アンワインドを呼び出すため、パフォーマンスが低下します。 __leave
ステートメントは、スタック アンワインドが発生しないため、より効率的です。
Abnormal Termination (異常終了)
longjmp ランタイム関数を使用して try-finally
ステートメントを終了すると、異常終了と見なされます。 __try
ステートメントにジャンプして入ることはできませんが、このステートメントからジャンプして出ることはできます。 出発点 (__try
ブロックの通常の終端) と処理先 (例外を処理する __except
ブロック) の間でアクティブなすべての __finally
ステートメントを実行する必要があります。 これは、"ローカル アンワインド" と呼ばれます。
__try
ブロックが、ブロックからのジャンプを含む任意の理由で完了前に終了した場合、スタックをアンワインドするプロセスで関連する __finally
ブロックが実行されます。 このような場合、AbnormalTermination
関数の戻り値は、__finally
ブロック内で呼び出されると true
になり、それ以外の場合は false
になります。
終了ハンドラーは、プロセスが try-finally
ステートメントの実行中に中止された場合は呼び出されません。
Microsoft 固有の仕様の終了