_set_se_translator

Win32 例外 (C 構造化例外) を C++ 型指定例外に変換するスレッドごとのコールバック関数を設定します。

構文

_se_translator_function _set_se_translator(
    _se_translator_function seTransFunction
);

パラメーター

seTransFunction
ユーザーが作成した C 構造化例外の変換関数へのポインター。

戻り値

_set_se_translator によって登録された前の変換関数へのポインターを返し、前の関数を後で復元できるようにします。 前の関数が設定されていない場合には、戻り値を使用して既定の動作を復元することができます。この値は nullptr になります。

解説

_set_se_translator 関数は、Win32 例外 (C 構造化例外) を C++ 型指定例外として処理する方法を提供します。 それぞれの C 例外が C++ catch ハンドラーによって処理されるようにするには、まず、特定のクラスの種類を C 例外に起因すると見なすために利用したり派生させたりできる、C 例外のラッパー クラスを定義します。 このクラスを使用するには、C 例外が発生するたびに内部例外処理メカニズムによって呼び出されるカスタム C 例外変換関数をインストールします。 変換関数内では、一致する C++ catch ハンドラーでキャッチできる任意の型例外をスローすることができます。

使用する場合は、このオプションを /EHa 使用 _set_se_translatorする必要があります。

カスタム変換関数を指定する場合は、変換関数の名前を引数として指定して _set_se_translator を呼び出します。 作成した変換関数は、try ブロックを持つスタックの関数呼び出しごとに 1 回呼び出されます。 既定の変換関数はありません。

変換関数は、C++ 型の例外をスローする以外のことは何もすべきではありません。 スローに加えて何かを行う場合 (ログ ファイルへの書き込みなど)、Translator 関数の呼び出しの数がプラットフォームに依存しているため、プログラムが期待どおりに動作しない可能性があります。

マルチスレッド環境では、変換関数は各スレッドとは別に管理されます。 新しい各スレッドは、それぞれの変換関数をインストールする必要があります。 したがって、各スレッドが、それぞれの変換処理を担当します。 _set_se_translator は 1 つのスレッドに対して固有であり、他の DLL では別の変換関数をインストールできます。

ユーザーが作成する seTransFunction 関数は、ネイティブにコンパイルされた関数である (/clr を使ってコンパイルしない) 必要があります。 それは引数として、符号なし整数と、Win32 _EXCEPTION_POINTERS 構造体へのポインターを取る必要があります。 引数はそれぞれ、Win32 API の GetExceptionCode 関数と GetExceptionInformation 関数の呼び出しの戻り値です。

typedef void (__cdecl *_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );

_set_se_translator の場合、CRT に動的にリンクするときに影響があります。プロセス内の別の DLL は _set_se_translator を呼び出す可能性があり、ハンドラーを独自のものに置換します。

マネージド コード (コンパイルされた/clrコード) またはネイティブ コードとマネージド コードの混在から使用_set_se_translatorする場合、トランスレーターはネイティブ コードでのみ生成される例外に影響します。 マネージド コードで生成されるマネージド例外 (System::Exception の発生時のものなど) はいずれも、変換関数経由ではルーティングされません。 Win32 関数 RaiseException を使用してマネージド コードで発生した例外や、ゼロ除算例外などのシステム例外が原因の例外は、変換プログラム経由でルーティングされます。

必要条件

ルーチンによって返される値 必須ヘッダー
_set_se_translator <eh.h>

互換性の詳細については、「 Compatibility」を参照してください。

例: __try 例外エラーの捕捉

この例では、呼び出しをラップして、構造化例外の変換プログラムを設定し、RAII クラス Scoped_SE_Translator で古いものを復元します。 このクラスを使用すると、スコープ固有の変換プログラムを 1 つの宣言として導入できます。 クラス デストラクターでは、制御がスコープから離れたときに、元の変換プログラムを復元します。

// crt_settrans.cpp
// compile with: cl /W4 /EHa crt_settrans.cpp
#include <stdio.h>
#include <windows.h>
#include <eh.h>
#include <exception>

class SE_Exception : public std::exception
{
private:
    const unsigned int nSE;
public:
    SE_Exception() noexcept : SE_Exception{ 0 } {}
    SE_Exception( unsigned int n ) noexcept : nSE{ n } {}
    unsigned int getSeNumber() const noexcept { return nSE; }
};

class Scoped_SE_Translator
{
private:
    const _se_translator_function old_SE_translator;
public:
    Scoped_SE_Translator( _se_translator_function new_SE_translator ) noexcept
        : old_SE_translator{ _set_se_translator( new_SE_translator ) } {}
    ~Scoped_SE_Translator() noexcept { _set_se_translator( old_SE_translator ); }
};

void SEFunc()
{
    __try
    {
        printf( "In __try, about to force exception\n" );
        int x = 5;
        int y = 0;
        int *p = &y;
        *p = x / *p;
    }
    __finally
    {
        printf( "In __finally\n" );
    }
}

void trans_func( unsigned int u, EXCEPTION_POINTERS* )
{
    throw SE_Exception( u );
}

int main()
{
    Scoped_SE_Translator scoped_se_translator{ trans_func };
    try
    {
        SEFunc();
    }
    catch( const SE_Exception& e )
    {
        printf( "Caught a __try exception, error %8.8x.\n", e.getSeNumber() );
    }
}
In __try, about to force exception
In __finally
Caught a __try exception, error c0000094.

例: SE_Exception エラーの捕捉

_set_se_translator によって提供される機能がマネージド コードでは使用できなくても、このマッピングをネイティブ コードで使用することは可能です。そのネイティブ コードが /clr スイッチのもとでコンパイルされている場合でも、ネイティブ コードで #pragma unmanaged を使用していることが示されている限り、それは可能です。 マップされるマネージド コード内で構造化例外がスローされる場合は、例外を生成および処理するコードを #pragma unmanaged でマークする必要があります。 次のコードは考えられる使用法を示しています。 詳細については、「プラグマ ディレクティブと __pragma および _Pragma キーワード」を参照してください。

// crt_set_se_translator_clr.cpp
// compile with: cl /W4 /clr crt_set_se_translator_clr.cpp
#include <windows.h>
#include <eh.h>
#include <stdio.h>
#include <exception>

int thrower_func( int i ) {
   int y = 0;
   int *p = &y;
   *p = i / *p;
   return 0;
}

class SE_Exception : public std::exception
{
private:
    const unsigned int nSE;
public:
    SE_Exception() noexcept : SE_Exception{ 0 } {}
    SE_Exception( unsigned int n ) noexcept : nSE{ n } {}
    unsigned int getSeNumber() const noexcept { return nSE; }
};

class Scoped_SE_Translator
{
private:
    const _se_translator_function old_SE_translator;
public:
    Scoped_SE_Translator( _se_translator_function new_SE_translator ) noexcept
        : old_SE_translator{ _set_se_translator( new_SE_translator ) } {}
    ~Scoped_SE_Translator() noexcept { _set_se_translator( old_SE_translator ); }
};

#pragma unmanaged
void my_trans_func( unsigned int u, PEXCEPTION_POINTERS )
{
    throw SE_Exception( u );
}

void DoTest()
{
    try
    {
        thrower_func( 10 );
    }
    catch( const SE_Exception& e )
    {
        printf( "Caught SE_Exception, error %8.8x\n", e.getSeNumber() );
    }
    catch(...)
    {
        printf( "Caught unexpected SEH exception.\n" );
    }
}
#pragma managed

int main() {
    Scoped_SE_Translator scoped_se_translator{ my_trans_func };

    DoTest();
}
Caught SE_Exception, error c0000094

関連項目

例外処理ルーチン
set_terminate
set_unexpected
terminate
unexpected\