Condividi tramite


_set_se_translator

Impostare una funzione di callback per thread per convertire le eccezioni Win32 (eccezioni strutturate C) in eccezioni tipate C++.

Sintassi

_se_translator_function _set_se_translator(
    _se_translator_function seTransFunction
);

Parametri

seTransFunction
Puntatore a una funzione di conversione di eccezioni strutturate C scritta dall'utente.

Valore restituito

Restituisce un puntatore alla funzione di conversione precedente registrata da _set_se_translator, in modo che la funzione precedente possa essere ripristinata in un secondo momento. Se non è stata impostata alcuna funzione precedente, il valore restituito può essere usato per ripristinare il comportamento predefinito. Questo valore può essere nullptr.

Osservazioni:

La funzione _set_se_translator consente di gestire le eccezioni Win32 (eccezioni strutturate C) come eccezioni tipizzate C++. Per consentire a ogni eccezione C di essere gestita da un gestore catch C++, è necessario definire precedentemente una classe wrapper di eccezioni C che può essere utilizzata o derivata per associare un tipo di classe specifico a un'eccezione C. Per utilizzare questa classe, installare una funzione di conversione delle eccezioni C personalizzata che viene chiamata dal meccanismo interno di gestione delle eccezioni ogni volta che viene generata un'eccezione C. All'interno della funzione di conversione, è possibile generare qualsiasi eccezione tipizzata che può essere rilevata da un gestore catch C++ corrispondente.

È necessario usare l'opzione /EHa quando si usa _set_se_translator.

Per specificare una funzione di traduzione personalizzata, chiamare _set_se_translator usando il nome della funzione di traduzione come argomento. La funzione di conversione scritta viene chiamata una volta per ogni chiamata di funzione nello stack con blocchi try. Non esiste alcuna funzione di traduzione predefinita.

La funzione di conversione non dovrebbe fare altro che generare un'eccezione tipizzata C++. Se non esegue alcuna operazione oltre a generare (ad esempio, la scrittura in un file di log), il programma potrebbe non comportarsi come previsto perché il numero di chiamate della funzione traduttore dipende dalla piattaforma.

In un ambiente con multithreading, le funzioni di conversione vengono mantenute separatamente per ogni thread. Ogni nuovo thread richiede l'installazione della propria funzione di conversione. Quindi, ogni thread è responsabile della propria gestione di conversione. _set_se_translator è specifico di un thread- un'altra DLL può installare una funzione di conversione diversa.

La seTransFunction funzione scritta deve essere una funzione compilata in modo nativo (non compilata con /clr). Deve accettare come argomenti un unsigned integer e un puntatore a una struttura _EXCEPTION_POINTERS di Win32. Gli argomenti sono i valori restituiti delle chiamate alle funzioni API Win32 GetExceptionCode e GetExceptionInformation, rispettivamente.

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

Per _set_se_translator vi sono implicazioni quando viene collegato dinamicamente a CRT; durante il processo un'altra DLL potrebbe chiamare _set_se_translator e sostituire il gestore con il proprio.

Quando si usa _set_se_translator codice gestito (codice compilato con /clr) o codice nativo misto e gestito, il traduttore influisce sulle eccezioni generate solo nel codice nativo. Tutte le eccezioni gestite generate nel codice gestito , ad esempio quando si generano System::Exception, non vengono instradate tramite la funzione traduttore. Le eccezioni generate nel codice gestito che utilizzano la funzione RaiseException Win32 o causate da un'eccezione di sistema come un'eccezione di divisione per zero vengono indirizzate attraverso il convertitore.

Requisiti

Ciclo Intestazione obbligatoria
_set_se_translator <eh.h>

Per altre informazioni sulla compatibilità, vedere Compatibility (Compatibilità).

Esempio: Rilevare un __try errore di eccezione

Questo esempio esegue il wrapping delle chiamate per impostare un traduttore di eccezioni strutturato e ripristinare quello precedente in una RAII classe , Scoped_SE_Translator. Questa classe consente di introdurre un traduttore specifico dell'ambito come singola dichiarazione. Il distruttore di classe ripristina il traduttore originale quando il controllo lascia l'ambito.

// 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.

Esempio: Errore catch SE_Exception

Anche se la funzionalità fornita da _set_se_translator non è disponibile nel codice gestito, è possibile usare questo mapping nel codice nativo, anche se tale codice nativo si trova in una compilazione nel /clr commutatore, purché il codice nativo sia indicato usando #pragma unmanaged. Se viene generata un'eccezione strutturata nel codice gestito di cui eseguire il mapping, il codice che genera e gestisce l'eccezione deve essere contrassegnato come #pragma unmanaged. Il codice seguente illustra un possibile utilizzo. Per altre informazioni, vedere Direttive Pragma e parole __pragma chiave e _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

Vedi anche

Routine di gestione delle eccezioni
set_terminate
set_unexpected
terminate
unexpected