_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
函式提供一種方式,以 C++ 類型化例外狀況處理 Win32 例外狀況 (C 結構化例外狀況)。 若要允許 C++ catch
處理常式處理每個 C 例外狀況,請先定義 C 例外狀況包裝函式類別,使用或衍生自這個類別即可將特定類別類型的屬性設為 C 例外狀況。 若要使用這個類別,請安裝內部例外狀況處理機制在每次引發 C 例外狀況時呼叫的自訂 C 例外狀況轉譯器函式。 在轉譯器函式內,您可以擲回相符 C++ catch
處理常式可攔截的任何類型化例外狀況。
當您使用 /EHa
_set_se_translator
時,必須使用 選項。
若要指定自定義翻譯函式,請使用翻譯函式的名稱作為其自變數來呼叫 _set_se_translator
。 每次在包含 try
區塊的堆疊叫用函式時,都會呼叫您所撰寫的轉譯器函式。 沒有預設的翻譯工具函式。
您的轉譯器函式只應該擲回 C++ 類型化例外狀況。 如果除了擲回以外的任何動作(例如寫入記錄檔,例如),您的程式可能不會如預期般運作,因為翻譯工具函式的調用數目與平台相關。
在多執行緒環境中,會分別維護每個執行緒的轉譯器函式。 每個新執行緒都需要安裝它自己的轉譯器函式。 因此,每個執行緒都會負責它自己的轉譯處理。 _set_se_translator
專屬於一個線程,另一個 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
,並將您的處理常式取代為它自己的處理常式。
當您從 Managed 程式代碼(使用 /clr
編譯的程式代碼)或混合原生和 Managed 程式代碼使用_set_se_translator
時,翻譯工具只會影響原生程式碼中產生的例外狀況。 Managed 程式代碼中產生的任何 Managed 例外狀況(例如引發 System::Exception
時)都不會透過翻譯工具函式路由傳送。 使用 Win32 函式 RaiseException
於 Managed 程式碼中所引發的例外狀況,或系統例外狀況所造成的除以零例外狀況這類例外狀況,都是透過轉譯器所傳遞。
需求
常式 | 必要的標頭 |
---|---|
_set_se_translator |
<eh.h> |
如需相容性詳細資訊,請參閱相容性。
範例:攔截 __try
例外狀況錯誤
此範例會包裝呼叫來設定結構化例外狀況翻譯工具,以及還原 類別Scoped_SE_Translator
中的RAII
舊呼叫。 這個類別可讓您將範圍特定的翻譯工具介紹為單一宣告。 當控件離開範圍時,類別解構函式會還原原始翻譯工具。
// 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
功能無法在 Managed 程式代碼中使用,但即使該機器碼是在 參數下的 /clr
編譯中,還是可以在機器碼中使用這個對應,只要使用 #pragma unmanaged
表示原生程式代碼。 如果在要對應的 Managed 程式代碼中擲回結構化例外狀況,則產生和處理例外狀況的程式代碼必須標示 #pragma unmanaged
為 。 下列程式碼會示範可能用法。 如需詳細資訊,請參閱 Pragma 指示詞和 __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