try-except ステートメント

try-except ステートメントは、C および C++ 言語での構造化例外処理をサポートする Microsoft 固有の拡張機能です。

    // . . .
    __try {
        // guarded code
    }
    __except ( /* filter expression */ ) {
        // termination code
    }
    // . . .

構文

try-except-statement:
__try compound-statement __except ( expression ) compound-statement

注釈

try-except ステートメントは、C および C++ 言語に対する Microsoft の拡張機能です。 これにより、通常はプログラムの実行を終了するイベントがいつ発生するかをターゲット アプリケーションが制御できるようになります。 このようなイベントは構造化 例外と呼ばれ、略して 例外 と呼ばれます。 これらの例外を処理するメカニズムは、 構造化例外処理 (SEH) と呼ばれます。

関連情報については、 try-finally ステートメントを参照してください。

例外は、ハードウェアベースまたはソフトウェアベースのいずれかです。 構造化例外処理は、アプリケーションがハードウェアまたはソフトウェアの例外から完全に復旧できない場合でも便利です。 SEH を使用すると、エラー情報を表示し、アプリケーションの内部状態をトラップして問題の診断に役立てることができます。 これは、再現が容易ではない断続的な問題に特に役立ちます。

構造化例外処理は、C と C++ の両方のソース ファイルに対して Win32 で動作します。 ただし、C++ 用に特別に設計されているわけではありません。 C++ 例外処理を使用して、コードの移植性を高めることができます。 また、C++ 例外処理は、任意の型の例外を処理できる点で柔軟性が高くなります。 C++ プログラムでは、ネイティブの C++ 例外処理 ( try、catch、throw ステートメント) を使用することをお勧めします。

__try句の後の複合ステートメントは、本文または保護されたセクションです。 __except式は、フィルター式とも呼ばれます。 その値によって、例外の処理方法が決まります。 __except句の後の複合ステートメントが例外ハンドラーです。 ハンドラーは、body セクションの実行中に例外が発生した場合に実行するアクションを指定します。 実行は次のように実行されます。

  1. 保護されたセクションが実行されます。

  2. 保護されたセクションの実行中に例外が発生しない場合は、 __except 句の後のステートメントで実行が続行されます。

  3. 保護されたセクションの実行中、または保護されたセクション呼び出しのルーチンで例外が発生した場合、 __except 式が評価されます。 指定可能な 3 つの値は次のとおりです。

    • EXCEPTION_CONTINUE_EXECUTION (-1)例外は無視されます。 例外が発生した時点で実行を続行します。

    • EXCEPTION_CONTINUE_SEARCH (0) 例外が認識されない。 引き続きスタックでハンドラーを検索し、最初に try-except ステートメントを含み、次に優先順位が最も高いハンドラーを検索します。

    • EXCEPTION_EXECUTE_HANDLER (1) 例外が認識される。 __except複合ステートメントを実行して例外ハンドラーに制御を転送し、__except ブロックの後で実行を続行します。

__except式は C 式として評価されます。 1 つの値、条件式演算子、またはコンマ演算子に制限されます。 より広範な処理が必要な場合、式は上記の 3 つの値のいずれかを返すルーチンを呼び出すことができます。

各アプリケーションは、独自の例外ハンドラーを持つことができます。

__tryステートメントにジャンプすることは有効ではありませんが、1 つから飛び出すには有効です。 try-except ステートメントの実行中にプロセスが終了した場合、例外ハンドラーは呼び出されません。

以前のバージョンとの互換性のために、コンパイラ オプション /Za (言語拡張機能を無効にする) が指定されていない限り、_try、_except、および_leaveは、__try__except、および__leaveのシノニムです。

__leave キーワード

__leave キーワードは、try-except ステートメントの保護されたセクション内でのみ有効であり、その効果は保護されたセクションの末尾にジャンプすることです。 例外ハンドラーの後の最初のステートメントで実行が続行されます。

gotoステートメントは保護されたセクションから飛び出すこともできます。try-finally ステートメントのようにパフォーマンスが低下することはありません。 これは、スタック アンワインドが発生しないためです。 ただし、goto ステートメントではなく、__leave キーワードを使用することをお勧めします。 その理由は、保護されたセクションが大きい場合や複雑な場合にプログラミングミスを犯す可能性が低いためです。

組み込み関数を処理する構造化例外

構造化例外処理には、 try-except ステートメントで使用できる 2 つの組み込み関数 ( GetExceptionCodeGetExceptionInformation) が用意されています

GetExceptionCode は、例外のコード (32 ビット整数) を返します。

組み込み関数 GetExceptionInformation は、例外に関する追加情報を含む EXCEPTION_POINTERS 構造体へのポインターを返します。 このポインターを使用すると、ハードウェア例外時に存在していたマシンの状態にアクセスできます。 構造は次のとおりです。

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

ポインター型 PEXCEPTION_RECORDPCONTEXT はインクルード ファイル <winnt.h> で定義され、 _EXCEPTION_RECORD_CONTEXT はインクルード ファイル <excpt.h で定義されます。>

例外ハンドラー内で GetExceptionCode を使用できます。 ただし、 GetExceptionInformation は例外フィルター式内でのみ使用できます。 それが指す情報は一般にスタック上にあり、制御が例外ハンドラーに転送されるときに使用できなくなります。

組み込み関数 AbnormalTermination は、終了ハンドラー内で使用できます。 try-finally ステートメントの本体が順番に終了する場合は、0 を返します。 それ以外の場合は、1 を返します。

<excpt.h> はこれらの組み込み関数の代替名をいくつか定義します。

GetExceptionCode_exception_code と同じです。

GetExceptionInformation_exception_info と同じです。

AbnormalTermination_abnormal_termination と同じです。

// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
    puts("in filter.");
    if (code == EXCEPTION_ACCESS_VIOLATION)
    {
        puts("caught AV as expected.");
        return EXCEPTION_EXECUTE_HANDLER;
    }
    else
    {
        puts("didn't catch AV, unexpected.");
        return EXCEPTION_CONTINUE_SEARCH;
    }
}

int main()
{
    int* p = 0x00000000;   // pointer to NULL
    puts("hello");
    __try
    {
        puts("in try");
        __try
        {
            puts("in try");
            *p = 13;    // causes an access violation exception;
        }
        __finally
        {
            puts("in finally. termination: ");
            puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
        }
    }
    __except(filter(GetExceptionCode(), GetExceptionInformation()))
    {
        puts("in except");
    }
    puts("world");
}

アウトプット

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

こちらも参照ください

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