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 を使用すると、エラー情報を表示し、問題の診断に役立つアプリケーションの内部状態をトラップすることができます。 特に、再現するのが難しい断続的な問題に対して役立ちます。

Note

構造化例外処理では、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 つの値の 1 つを返すルーチンを式で呼び出すことができます。

各アプリケーションが独自の例外ハンドラーを持つ場合があります。

__try ステートメント内に移動することはできませんが、外に移動することはできます。 例外ハンドラーは、try-except ステートメントの実行中にプロセスが中止された場合は呼び出されません。

以前のバージョンとの互換性を確保するために、コンパイラ オプション /Za (言語拡張機能の無効化) が指定されていない限り、_try_except、および _leave__try__except、および __leave と同意語です。

__leave キーワード

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

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

構造化例外処理の組み込み関数

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

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++)
キーワード