Structured Exception Handling (C/C++)

El control de excepciones estructurados (SEH) es una extensión de Microsoft para C y C++ para controlar determinadas situaciones de código excepcionales, como errores de hardware, correctamente. Aunque Windows y Microsoft C++ admiten SEH, se recomienda usar el control de excepciones de C++ estándar ISO en el código de C++. Hace que el código sea más portable y flexible. Sin embargo, para mantener el código existente o en determinadas clases de programas, quizás tenga que seguir utilizando SEH.

Específico de Microsoft:

Grammar

try-except-statement :
__try compound-statement __except ( filter-expression ) compound-statement

try-finally-statement :
__try compound-statement __finally compound-statement

Comentarios

Con SEH, puede asegurarse de que los recursos, como los bloques de memoria y los archivos, se liberen correctamente si la ejecución termina inesperadamente. También se pueden controlar determinados problemas, como memoria insuficiente, mediante código estructurado conciso que no utiliza instrucciones goto ni realiza pruebas detalladas de los códigos de retorno.

Las try-except instrucciones y try-finally a las que se hace referencia en este artículo son extensiones de Microsoft a los lenguajes C y C++. Admiten SEH al permitir que las aplicaciones tomen el control de un programa después de que se produzcan eventos que de lo contrario finalizarían la ejecución. Aunque SEH funciona con archivos de código fuente de C++, no está diseñado específicamente para C++. Si usa SEH en un programa de C++ que se compila mediante la /EHa opción o /EHsc , se llama a los destructores para objetos locales, pero es posible que otro comportamiento de ejecución no sea lo que espera. Para más información, consulte el ejemplo más adelante en este artículo. En la mayoría de los casos, en lugar de SEH, se recomienda usar el control de excepciones de C++ estándar ISO. Mediante el control de excepciones de C++, puede asegurarse de que el código sea más portátil y puede controlar excepciones de cualquier tipo.

Si tiene código C que usa SEH, puede mezclarlo con código de C++ que use el control de excepciones de C++. Para más información, consulte Control de excepciones estructuradas en C++.

Existen dos mecanismos de SEH:

Estas dos clases de controladores son distintas, pero están estrechamente relacionadas mediante un proceso conocido como desenredo de la pila. Cuando se produce una excepción estructurada, Windows busca el controlador de excepciones instalado más recientemente que está activo actualmente. El controlador puede hacer una de tres cosas:

  • No se reconoce la excepción y se pasa el control a otros controladores (EXCEPTION_CONTINUE_SEARCH).

  • Reconocer la excepción pero descartarla (EXCEPTION_CONTINUE_EXECUTION).

  • Reconocer la excepción y controlarla (EXCEPTION_EXECUTE_HANDLER).

El controlador de excepciones que reconoce la excepción puede no estar en la función que se estaba ejecutando cuando se produjo la excepción. Puede estar en una función situada mucho más arriba en la pila. La función que se está ejecutando actualmente y todas las demás funciones del marco de pila finalizan. Durante este proceso, la pila no se desenlaza. Es decir, las variables locales no estáticas de las funciones terminadas se borran de la pila.

A medida que se desenreda la pila, el sistema operativo llama a cualquier controlador de terminación que haya escrito para cada función. Mediante un controlador de terminación, se limpian recursos que de lo contrario quedarían abiertos debido a una finalización anormal. Si se ha entrado en una sección crítica, se puede salir de ella en el controlador de terminación. Si el programa se va a cerrar, se pueden realizar otras tareas de mantenimiento como cerrar y quitar archivos temporales.

Pasos siguientes

Ejemplo

Como se ha explicado anteriormente, se llama a los destructores de los objetos locales si se utiliza SEH en un programa de C++ y se compila con la opción /EHa o /EHsc. Sin embargo, el comportamiento durante la ejecución puede no ser el esperado si también se utilizan excepciones de C++. En este ejemplo se muestran estas diferencias de comportamiento.

#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;
}

Si se utiliza /EHsc para compilar este código pero el control de pruebas local CPPEX está sin definir, no se ejecuta el destructor TestClass. La salida es similar a esta:

Triggering SEH exception
Executing SEH __except block

Si se utiliza /EHsc para compilar el código y CPPEX se define mediante /DCPPEX (para que se produzca una excepción de C++), se ejecuta el destructor TestClass y la salida es similar a la siguiente:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Si usa /EHa para compilar el código, el destructor TestClass se ejecuta si se produjo una excepción mediante una expresión throw estándar de C++ o mediante SEH. Es decir, si CPPEX se define o no. La salida es similar a esta:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Para más información, consulte /EH(Modelo de control de excepciones).

FIN de Específicos de Microsoft

Consulte también

Control de excepciones
Palabras clave
<exception>
Controlar errores y excepciones
Control estructurado de excepciones (Windows)