_set_se_translator
Win32 の例外 (C の構造化例外) を C++ の型付き例外として処理します。
_se_translator_function _set_se_translator(
_se_translator_function seTransFunction
);
パラメーター
- seTransFunction
独自の C 構造化例外の変換関数へのポインター。
戻り値
_set_se_translator 関数の前回の呼び出しで登録された変換関数へのポインターを返します。これにより、以前の関数を後で復元できます。 以前の関数が登録されていない場合は、戻り値 (NULL でも可) を使用して既定の動作を復元できます。
解説
_set_se_translator 関数は、Win32 の例外 (C の構造化例外) を C++ の型付き例外として処理する手段を提供します。 C の例外を C++ の catch ハンドラーで処理するには、まず C 例外のラップ クラスを定義して特定のクラス型としての属性を与え、使用できる (派生できる) ようにします。 このクラスを使用するには、独自の C の例外変換関数を設定します。この例外変換関数は、C の例外が発生するたびに内部的な例外処理機構から呼び出されます。 変換関数の中から任意の型の例外をスローし、対応する C++ の catch ハンドラーでキャッチさせることができます。
_set_se_translator を使用する場合は /EHa を使用する必要があります。
独自の変換関数を指定するには、変換関数の名前を引数に指定して _set_se_translator 関数を呼び出します。 変換関数は、try ブロックを持つスタック上で関数を呼び出すたびに 1 回呼び出されます。 既定の変換関数はありません。
変換関数では、C++ の型付き例外をスローする以外の処理は何も実行しないでください。 ログ ファイルに書き込むなど、例外をスローする以外に何かを実行すると、変換関数が呼び出される回数はプラットフォームに依存するので、プログラムが予測どおりに動作しないことがあります。
マルチスレッド環境では、変換関数はスレッドごとに個別に管理されます。 新しいスレッドごとに、専用の変換関数を設定する必要があります。 したがって、個々のスレッドが各変換処理を担当します。 _set_se_translator は 1 つのスレッドに固有のもので、DLL が異なると、インストールされる変換関数も異なります。
seTransFunction 関数は、(/clr でコンパイルした関数ではなく) ネイティブでコンパイルした関数にする必要があります。 このとき、符号なし整数と Win32 _EXCEPTION_POINTERS 構造体を引数に使用する必要があります。 これらの引数は、それぞれ Win32 API の GetExceptionCode 関数と GetExceptionInformation 関数を呼び出した場合の戻り値です。
typedef void (*_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );
_set_se_translator は、CRT と動的にリンクするときに影響を及ぼします。これは、プロセス内の他の DLL が _set_se_translator を呼び出し、ハンドラーが置き換えられる可能性があるためです。
/clr を使用してコンパイルするマネージ コードまたはネイティブ コードとマネージ コードの組み合わせから _set_se_translator を使用する場合、変換関数がネイティブ コードによって生成される例外のみに影響することに注意してください。 System::Exception などのマネージ コードで生成されるマネージ例外は、変換関数を経由しません。 Win32 関数 RaiseException を使用するか、または 0 で除算などのシステム例外によってマネージ コードで生成されるマネージ例外は、変換関数を経由します。
必要条件
ルーチン |
必須ヘッダー |
---|---|
_set_se_translator |
<eh.h> |
_set_se_translator が提供する機能は、/clr:pure コンパイル オプションを使用してコンパイルされたコードでは使用できません。
互換性の詳細については、「C ランタイム ライブラリ」の「互換性」を参照してください。
使用例
// crt_settrans.cpp
// compile with: /EHa
#include <stdio.h>
#include <windows.h>
#include <eh.h>
void SEFunc();
void trans_func( unsigned int, EXCEPTION_POINTERS* );
class SE_Exception
{
private:
unsigned int nSE;
public:
SE_Exception() {}
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
int main( void )
{
try
{
_set_se_translator( trans_func );
SEFunc();
}
catch( SE_Exception e )
{
printf( "Caught a __try exception with SE_Exception.\n" );
}
}
void SEFunc()
{
__try
{
int x, y=0;
x = 5 / y;
}
__finally
{
printf( "In finally\n" );
}
}
void trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )
{
printf( "In trans_func.\n" );
throw SE_Exception();
}
_set_se_translator が提供する機能はマネージ コードで使用できませんが、#pragma unmanaged を使用してネイティブ コードを指定すると、/clr スイッチを使用してコンパイルされたネイティブ コードでもこのマッピングを使用できます。 マップするマネージ コードで構造化例外がスローされる場合、例外を生成して処理するコードには pragma のマークを付ける必要があります。 この使用例を次のコードに示します。 詳細については、「Pragma Directives and the __Pragma Keyword」を参照してください。
// crt_set_se_translator_clr.cpp
// compile with: /clr
#include <windows.h>
#include <eh.h>
#include <assert.h>
#include <stdio.h>
int thrower_func(int i) {
int j = i/0;
return 0;
}
class CMyException{
};
#pragma unmanaged
void my_trans_func(unsigned int u, PEXCEPTION_POINTERS pExp )
{
printf("Translating the structured exception to a C++"
" exception.\n");
throw CMyException();
}
void DoTest()
{
try
{
thrower_func(10);
}
catch(CMyException e)
{
printf("Caught CMyException.\n");
}
catch(...)
{
printf("Caught unexpected SEH exception.\n");
}
}
#pragma managed
int main(int argc, char** argv) {
_set_se_translator(my_trans_func);
DoTest();
return 0;
}
同等の .NET Framework 関数
該当なし標準 C 関数を呼び出すには、PInvoke を使用します。詳細については、「プラットフォーム呼び出しの例」を参照してください。