Tratamento de exceções estruturado (C/C++)
O SEH (tratamento de exceção estruturado) é uma extensão da Microsoft para C e C++ para lidar com determinadas situações de código excepcionais, como falhas de hardware, normalmente. Embora o Windows e o Microsoft C++ ofereçam suporte ao SEH, recomendamos o uso do tratamento de exceções no C++ padrão ISO para códigos em C++. Isso torna seu código mais portátil e flexível. Entretanto,para manutenção de código existente ou em tipos específicos de programas, você ainda pode precisar do SEH.
Específico da Microsoft:
Gramática
try-except-statement
:
__try
compound-statement
__except
(
filter-expression
)
compound-statement
try-finally-statement
:
__try
compound-statement
__finally
compound-statement
Comentários
Com o SEH, é possível garantir que os recursos, como blocos e arquivos de memória, sejam lançados corretamente se a execução for finalizada inesperadamente. Você também pode controlar problemas específicos como, por exemplo, memória insuficiente, usando um código estruturado e conciso que não confia em instruções goto
ou em testes elaborados de códigos de retorno.
As instruções try-except
e try-finally
mencionadas neste artigo são extensões da Microsoft para as linguagens C e C++. Elas oferecem suporte ao SEH permitindo que os aplicativos controlem um programa após os eventos que, caso contrário, finalizariam a execução. Ainda que o SEH funcione com arquivos de origem C++, ele não é projetado especificamente para C++. Se você usar o SEH em um programa C++ compilado com o uso da opção /EHa
ou /EHsc
, os destruidores de objetos locais são chamados, mas outros comportamentos de execução podem não ser os esperados. Para obter uma ilustração, consulte o exemplo posteriormente neste artigo. Na maioria dos casos, em vez do SEH, nós recomendamos que você use o padrão ISO de manipulação de exceção C++. Usando o tratamento de exceções C++, é possível garantir que o seu código seja mais portátil e tratar exceções de qualquer tipo.
Se você tiver um código C que usa SEH, poderá misturá-lo com o código C++ que usa tratamento de exceção C++. Para obter informações, consulte Tratar exceções estruturadas no C++.
Existem dois mecanismos de SEH:
Manipuladores de exceções, ou blocos
__except
, que podem responder ou ignorar a exceção com base no valorfilter-expression
. Para obter mais informações, confira Instruçãotry-except
.Manipuladores de terminação, ou blocos
__finally
, que são sempre chamados, independentemente de uma exceção causar o encerramento ou não. Para obter mais informações, confira Instruçãotry-finally
.
Esses dois tipos dos manipuladores são distintos, mas estão intimamente relacionados por meio de um processo conhecido como deslocamento da pilha. Quando uma exceção estruturada ocorre, o Windows procura o manipulador de exceção recentemente instalado que está atualmente ativo. O manipulador pode executar uma de três ações:
Não reconhecer a exceção e não passar o controle para outros manipuladores (
EXCEPTION_CONTINUE_SEARCH
).Reconhecer a exceção, mas ignorá-la (
EXCEPTION_CONTINUE_EXECUTION
).Confirmar a exceção e manipulá-la (
EXCEPTION_EXECUTE_HANDLER
).
O manipulador de exceções que reconhece a exceção pode não estar na função em execução no momento da exceção. Ele pode estar em uma função muito mais alta na pilha. A função em execução no momento e quaisquer outras funções no quadro de pilhas são terminadas. Durante esse processo, a pilha é deslocada. Ou seja, variáveis não estáticas locais de funções terminadas são desmarcadas da pilha.
Como o sistema operacional desenrola a pilha, ele chama todos os manipuladores de término escritos para cada função. Usando um manipulador de término, você limpa os recursos que, caso contrário, permaneceriam abertos devido a um encerramento anormal. Se você tiver entrado em uma seção crítica, será possível sair dela no manipulador de término. Quando o programa estiver prestes a fechar, será possível executar outras tarefas de manutenção como fechar e remover os arquivos temporários.
Próximas etapas
Exemplo
Conforme mencionado anteriormente, os destruidores de objetos locais são chamados se você usar SEH em um programa C/C++ e compilar usando a opção /EHa
ou /EHsc
. No entanto, o comportamento durante a execução pode não ser o esperado se você também estiver usando exceções C++. Esse exemplo demonstra essas diferenças de comportamento.
#include <stdio.h>
#include <Windows.h>
#include <exception>
class TestClass
{
public:
~TestClass()
{
printf("Destroying TestClass!\n");
}
};
__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
printf("Throwing C++ exception\n");
throw std::exception("");
#else
printf("Triggering SEH exception\n");
volatile int *pInt = 0x00000000;
*pInt = 20;
#endif
}
__declspec(noinline) void TestExceptions()
{
TestClass d;
TestCPPEX();
}
int main()
{
__try
{
TestExceptions();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("Executing SEH __except block\n");
}
return 0;
}
Se você usar /EHsc
para compilar esse código, mas a macro de controle de teste local CPPEX
estiver indefinida, o destruidor TestClass
não é executado. A saída tem esta aparência:
Triggering SEH exception
Executing SEH __except block
Se você usar /EHsc
para compilar o código e CPPEX
estiver definido por meio do uso de /DCPPEX
(de modo que uma exceção seja gerada), o destruidor TestClass
é executado, e a saída é parecida com essa:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
Se você usar /EHa
para compilar o código, o destruidor TestClass
executará se uma exceção foi lançada usando uma expressão throw
C++ padrão ou usando SEH. Ou seja, se CPPEX
está definido ou não. A saída tem esta aparência:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
Para obter mais informações, consulte /EH
(Modelo de tratamento de exceções).
FIM Específico da Microsoft
Confira também
Manuseio de exceção
Palavras-chave
<exception>
Erros e tratamento de exceções
Tratamento de exceções estruturado (Windows)