_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 GetExceptionCodeGetExceptionInformation 函式的傳回值。

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

另請參閱

例外狀況處理常式
set_terminate
set_unexpected
terminate
unexpected