_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
ハンドラーでキャッチできる任意の型例外をスローすることができます。
_set_se_translator
を使用する場合は、/EHa
オプションを使用する必要があります。
カスタム変換関数を指定する場合は、変換関数の名前を引数として指定して _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