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++ 例外処理メカニズム (trycatch、および throw ステートメント) を使用することをお勧めします。

__try 句の後の複合ステートメントは、保護されたセクションです。 __finally 句の後の複合ステートメントは、終了ハンドラーです。 ハンドラーは、保護されたセクションが例外によって終了したか (異常終了)、標準的なフォール スルーで終了したか (正常終了) にかかわらず、それが終了したときに実行する一連の操作を指定します。

制御は、単純な順次実行 (フォール スルー) によって __try ステートメントに到達します。 制御が __try に入ると、その関連ハンドラーがアクティブになります。 制御のフローが try ブロックの終わりに到達すると、次のように実行は処理されます。

  1. 終了ハンドラーが呼び出されます。

  2. 終了ハンドラーが完了すると、__finally ステートメントの後から実行が続けられます。 保護されたセクションがどのように終了したかに関係なく (たとえば、保護された本体外の goto または return ステートメント経由)、終端ハンドラーは、制御フローが保護されたセクションの外部に移動する "前" に実行されます。

    __finally ステートメントは適切な例外ハンドラーの検索をブロックしません。

ブロックで __try 例外が発生した場合、オペレーティング システムは例外のハンドラーを見つける必要があります。そうしないと、プログラムが失敗します。 ハンドラーが見つかった場合は、任意およびすべての __finally ブロックが実行され、ハンドラーで実行が再開されます。

たとえば、次の図に示すように、一連の関数呼び出しで、関数 A を関数 D にリンクするとします。 各関数には、1 つの終了ハンドラーがあります。 関数 D で例外が発生し、A で処理されると、スタックがアンワインドされるときに、終了ハンドラーは D、C、B の順に呼び出されます。

Diagram of the order of termination handler execution.

この図は、関数 B を呼び出す関数 A から始まり、関数 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 固有の仕様の終了

関連項目

終了ハンドラーの記述
構造化例外処理 (C/C++)
キーワード
終了ハンドラー構文