Compartir a través de


Control estructurado de excepciones (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 portátil y flexible. Sin embargo, para mantener el código existente o para determinados tipos de programas, es posible que tenga que usar SEH.

Específico de Microsoft:

Gramática

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

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

Observaciones

Con SEH, puede asegurarse de que los recursos, como bloques de memoria y archivos, se liberan correctamente si la ejecución finaliza inesperadamente. También puede controlar problemas específicos (por ejemplo, memoria insuficiente) mediante código estructurado conciso que no se basa en goto instrucciones ni pruebas elaboradas de 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 obtengan el control de un programa después de los 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 obtener una ilustración, vea 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 es más portátil y puede controlar excepciones de cualquier tipo.

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

Hay dos mecanismos SEH:

Estos dos tipos de controladores son distintos, pero están estrechamente relacionados a través de un proceso conocido como desenredado 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 estas 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).

Es posible que el controlador de excepciones que reconozca la excepción no esté en la función que se estaba ejecutando cuando se produjo la excepción. Puede estar en una función mucho mayor 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 desenlazada. Es decir, las variables locales no estáticas de las funciones terminadas se borran de la pila.

A medida que desenreda la pila, el sistema operativo llama a cualquier controlador de terminación que haya escrito para cada función. Mediante el uso de un controlador de terminación, se limpian los recursos que, de lo contrario, permanecerán abiertos debido a una terminación anómala. Si ha escrito una sección crítica, puede salir de ella en el controlador de terminación. Cuando el programa se apague, puede realizar otras tareas de limpieza, como cerrar y quitar archivos temporales.

Pasos siguientes

Ejemplo

Como se indicó anteriormente, se llama a destructores para objetos locales si usa SEH en un programa de C++ y lo compila mediante la /EHa opción o /EHsc . Sin embargo, es posible que el comportamiento durante la ejecución no sea lo que espera si también usa 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 usa /EHsc para compilar este código, pero la macro CPPEX de control de prueba local no está definida, el TestClass destructor no se ejecuta. La salida es similar a esta:

Triggering SEH exception
Executing SEH __except block

Si usa /EHsc para compilar el código y CPPEX se define mediante /DCPPEX (para que se produzca una excepción de C++), el TestClass destructor se ejecuta y la salida tiene este aspecto:

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

Si usa /EHa para compilar el código, el TestClass destructor ejecuta si se produjo una excepción mediante una expresión estándar de C++ throw 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 obtener más información, consulte /EH (Modelo de control de excepciones).

END específico de Microsoft

Consulte también

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