_set_se_translator
Defina uma função de retorno de chamada por thread para converter exceções do Win32 (exceções estruturadas em C) em exceções tipadas em C++.
Sintaxe
_se_translator_function _set_se_translator(
_se_translator_function seTransFunction
);
Parâmetros
seTransFunction
Ponteiro para uma função conversora de exceção estruturada de C que você escreve.
Valor retornado
Retorna um ponteiro para a função conversora anterior registrada por _set_se_translator
, de modo que a função anterior possa ser restaurada posteriormente. Se nenhuma função anterior tiver sido definida, o valor retornado poderá ser usado para restaurar o comportamento padrão; esse valor pode ser nullptr
.
Comentários
A função _set_se_translator
fornece um meio para manipular exceções do Win32 (exceções C estruturadas) como exceções tipadas C++. Para permitir que cada exceção de C seja manipulada por um manipulador catch
C++, primeiro defina uma classe wrapper de exceção de C que possa ser usada – ou da qual seja possível obter uma classe derivada – para atribuir um tipo de classe específico a uma exceção de C. Para usar essa classe, instale uma função personalizada de conversão da exceção de C, chamada pelo mecanismo interno de manipulação de exceção sempre que uma exceção de C é gerada. Dentro de sua função translator, você pode gerar qualquer exceção tipada que pode ser capturada por um manipulador catch
C++ correspondente.
Você deve usar a /EHa
opção ao usar _set_se_translator
o .
Para especificar uma função de conversão personalizada, chame _set_se_translator
usando o nome da função de conversão como argumento. A função de conversão que você grava é chamada uma vez para cada invocação de função na pilha que tem blocos try
. Não há nenhuma função conversora padrão.
Sua função conversora não deve fazer nada além de gerar uma exceção tipada C++. Se ele fizer algo além de lançar (como gravar em um arquivo de log, por exemplo), seu programa pode não se comportar conforme o esperado porque o número de invocações da função tradutor depende da plataforma.
Em um ambiente multithreaded, funções de conversão são mantidas separadamente para cada thread. Cada novo thread precisa instalar sua própria função conversora. Portanto, cada thread é responsável pela sua própria manipulação de encerramento. _set_se_translator
é específico para um thread; outra DLL pode instalar uma função de conversão diferente.
A função seTransFunction
que você escreve deve ser uma função compilada de modo nativo (não compilada com /clr
). Ela precisa levar como argumentos um inteiro sem sinal e um ponteiro para uma estrutura _EXCEPTION_POINTERS
Win32. Os argumentos são os valores retornados das chamadas às funções GetExceptionCode
e GetExceptionInformation
de API do Win32, respectivamente.
typedef void (__cdecl *_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );
Para _set_se_translator
, há implicações ao vincular dinamicamente ao CRT; outra DLL no processo pode chamar _set_se_translator
e substituir o manipulador usado por você pelo manipulador da própria DLL.
Quando você usa _set_se_translator
a partir de código gerenciado (código compilado com /clr
) ou código nativo e gerenciado misto, o tradutor afeta apenas as exceções geradas no código nativo. Exceções gerenciadas geradas em código gerenciado (por exemplo, ao gerar System::Exception
) não são roteadas por meio da função conversora. Exceções geradas em código gerenciado usando a função RaiseException
Win32 ou causadas por uma exceção do sistema como uma exceção de divisão por zero são roteadas por meio da conversora.
Requisitos
Rotina | Cabeçalho necessário |
---|---|
_set_se_translator |
<eh.h> |
Para obter informações sobre compatibilidade, consulte Compatibilidade.
Exemplo: capturar erro de exceção __try
Este exemplo encapsula as chamadas para definir um conversor de exceção estruturado e restaurar o antigo em uma RAII
classe, a Scoped_SE_Translator
. Essa classe permite que você introduza um conversor específico do escopo como uma única declaração. O destruidor de classe restaura o conversor original quando o controle sai do escopo.
// 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.
Exemplo: capturar erro SE_Exception
Embora a funcionalidade fornecida pela _set_se_translator
não esteja disponível em código gerenciado, é possível usar esse mapeamento em código nativo, mesmo que o código nativo esteja em uma compilação na opção /clr
, desde que o código nativo seja indicado usando #pragma unmanaged
. Se uma exceção estruturada estiver sendo lançada em código gerenciado que deveria ser mapeado, o código que gera e manipula a exceção deverá ser marcado com #pragma unmanaged
. O código a seguir mostra um uso possível. Para obter mais informações, confira Diretivas pragma e as palavras-chave __pragma
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
Confira também
Rotinas de tratamento de exceções
set_terminate
set_unexpected
terminate
unexpected