Partage via


_set_se_translator

Définissez une fonction de rappel par thread pour traduire des exceptions Win32 (exceptions structurées C) en exceptions typées C++.

Syntaxe

_se_translator_function _set_se_translator(
    _se_translator_function seTransFunction
);

Paramètres

seTransFunction
Pointeur vers une fonction de traduction d'exceptions structurées C que vous écrivez.

Valeur retournée

Retourne un pointeur vers la précédente fonction de traduction enregistrée par _set_se_translator, afin qu'elle puisse être restaurée plus tard. Si aucune fonction précédente n'a été définie, la valeur de retour peut être utilisée pour restaurer le comportement par défaut ; cette valeur peut être nullptr.

Notes

La fonction _set_se_translator permet de gérer les exceptions Win32 (exceptions structurées C) en tant qu'exceptions typées C++. Pour que chaque exception C soit gérée par un gestionnaire catch C++, définissez d'abord une classe wrapper d'exceptions C qui peut être utilisée, ou dérivée, pour attribuer un type de classe spécifique à une exception C. Pour utiliser cette classe, installez une fonction de traduction d'exception C personnalisée appelée par le mécanisme de gestion des exceptions interne chaque fois qu'une exception C est levée. Dans votre fonction de traduction, vous pouvez lever n'importe quelle exception typée qui peut être interceptée par un gestionnaire catch C++ correspondant.

Vous devez utiliser l’option /EHa lorsque vous utilisez _set_se_translator.

Pour spécifier une fonction de traduction personnalisée, appelez _set_se_translator à l’aide du nom de votre fonction de traduction comme argument. La fonction de traduction que vous écrivez est appelée une fois pour chaque appel de fonction sur la pile contenant des blocs try. Il n’existe aucune fonction de traducteur par défaut.

Votre fonction de traduction se contente de lever une exception typée C++. S’il effectue quelque chose en plus de lever (par exemple, l’écriture dans un fichier journal), votre programme peut ne pas se comporter comme prévu, car le nombre d’appels de la fonction translator dépend de la plateforme.

Dans un environnement multithread, les fonctions de traduction sont gérées séparément pour chaque thread. Chaque nouveau thread doit installer sa propre fonction de traduction. Par conséquent, chaque thread est responsable de sa propre gestion de traduction. _set_se_translator est spécifique à un thread- une autre DLL peut installer une fonction de traduction différente.

La seTransFunction fonction que vous écrivez doit être une fonction compilée en mode natif (non compilée avec /clr). Elle doit utiliser un entier non signé et un pointeur vers une structure Win32 _EXCEPTION_POINTERS comme arguments. Les arguments sont les valeurs de retour des appels aux fonctions API Win32 GetExceptionCode et GetExceptionInformation, respectivement.

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

Pour _set_se_translator, la liaison dynamique au CRT a des conséquences ; une autre DLL du processus peut appeler _set_se_translator et remplacer votre gestionnaire par le sien.

Lorsque vous utilisez _set_se_translator du code managé (code compilé avec /clr) ou du code natif et managé mixte, le traducteur affecte uniquement les exceptions générées dans le code natif. Les exceptions managées générées dans le code managé (par exemple, lors du déclenchement System::Exception) ne sont pas routées via la fonction translator. Les exceptions générées en code managé à l'aide de la fonction Win32 RaiseException ou provoquées par une exception système telle qu'une exception de division par zéro sont acheminées via le traducteur.

Spécifications

Routine En-tête requis
_set_se_translator <eh.h>

Pour plus d’informations sur la compatibilité, consultez Compatibility.

Exemple : Erreur intercepter l’exception __try

Cet exemple encapsule les appels pour définir un traducteur d’exceptions structurées et restaurer l’ancien dans une RAII classe. Scoped_SE_Translator Cette classe vous permet d’introduire un traducteur spécifique à l’étendue en tant que déclaration unique. Le destructeur de classe restaure le traducteur d’origine lorsque le contrôle quitte l’étendue.

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

Exemple : Erreur intercepter SE_Exception

Bien que les fonctionnalités fournies par _set_se_translator ne soient pas disponibles dans le code managé, il est possible d’utiliser ce mappage dans le code natif, même si ce code natif se trouve dans une compilation sous le /clr commutateur, tant que le code natif est indiqué à l’aide #pragma unmanaged. Si une exception structurée est levée dans le code managé à mapper, le code qui génère et gère l’exception doit être marqué #pragma unmanaged. Le code suivant illustre une utilisation possible. Pour plus d’informations, consultez les directives Pragma et les __pragma mots clés._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

Voir aussi

Routines de gestion des exceptions
set_terminate
set_unexpected
terminate
unexpected