/EH (Modelo de control de excepciones)

Especifica la compatibilidad del modelo de control de excepciones que genera el compilador. Los argumentos especifican si se debe aplicar catch(...) la sintaxis tanto a las excepciones estructuradas como a las estándar de C++, si el código extern"C" se supone a throw las excepciones y si se deben optimizar determinadas comprobaciones noexcept.

Sintaxis

/EHa[-]
/EHs[-]
/EHc[-]
/EHr[-]

Argumentos

a
Habilita el desenredado de la pila estándar de C++. Detecta las excepciones estructuradas (asincrónicas) y el estándar de C++ (sincrónicas) al usar la sintaxis catch(...). /EHa invalida los argumentos /EHs y /EHc.

s
Habilita el desenredado de la pila estándar de C++. Detecta solo las excepciones estándar de C++ cuando se usa la sintaxis catch(...). A menos que también se especifique /EHc, el compilador asume que las funciones declaradas como extern "C" pueden throw ser una excepción de C++.

c
Cuando se usa con /EHs, el compilador asume que las funciones declaradas como extern "C" nunca throw son una excepción de C++. No tiene ningún efecto cuando se usa con /EHa (es decir, /EHca es equivalente a /EHa). /EHc se omite si no se especifica /EHs o /EHa.

r
Indica al compilador que genere siempre las comprobaciones de terminación en tiempo de ejecución para todas las funciones noexcept . De forma predeterminada, las comprobaciones en tiempo de ejecución para noexcept pueden optimizarse si el compilador determina que la función solo llame a funciones que no producen excepciones. Esta opción proporciona conformidad estricta con C++ a cambio de algún código adicional. /EHr se omite si no se especifica /EHs o /EHa.

-
Borra el argumento de la opción anterior. Por ejemplo, /EHsc- se interpreta como /EHs /EHc- y es equivalente a /EHs.

Los argumentos /EH se pueden especificar por separado o combinados, en cualquier orden. Si se especifica más de una instancia del mismo argumento, la última invalidará las anteriores. Por ejemplo, /EHr- /EHc /EHs es igual que /EHscr- y /EHscr- /EHr tiene el mismo efecto que /EHscr.

Comentarios

Comportamiento del control de excepciones predeterminado

El compilador siempre genera el código que admite el control de excepciones estructuradas asíncronas (SEH). De manera predeterminada (es decir, si no se especifica ninguna opción /EHsc, /EHs o /EHa), el compilador admite SEH controladores en la cláusula nativa de C++ catch(...). Sin embargo, también genera código que solo admite parcialmente las excepciones de C++. El código de desenredado de excepciones predeterminado no destruye los objetos de C++ automáticos fuera de los bloques try que se salen del ámbito debido a una excepción. Las pérdidas de recursos y el comportamiento no definido pueden dar lugar cuando se produce una excepción de C++.

Control de excepciones estándar de C++

La compatibilidad total del compilador con el modelo de control de excepciones estándar de C++ que desenreda de forma segura los objetos de la pila requiere /EHsc (recomendado), /EHso /EHa.

Si usa /EHs o /EHsc, las cláusulas catch(...) no detectarán catch las excepciones estructuradas asincrónicas. Las infracciones de acceso y las excepciones administradas System.Exception no se detectan. Además, cuando se produce una excepción asincrónica, los objetos en el ámbito no se destruyen, incluso si el código controla la excepción asincrónica. Este comportamiento es un argumento para no tratar las excepciones estructuradas no controladas. En cambio, considere estas excepciones como irrecuperables.

Cuando se usa /EHs o /EHsc, el compilador presupone que las excepciones solo pueden producirse en una instrucción throw o en una llamada de función. Esto permite que el compilador elimine el código para realizar el seguimiento de vida útil de muchos objetos que no se pueden desenredar, lo que puede reducir significativamente el tamaño del código. Si usa /EHa, la imagen ejecutable puede ser mayor y más lenta, ya que el compilador no optimiza try los bloques de manera tan agresivamente. También deja en los filtros de excepción que limpian automáticamente los objetos locales, incluso si el compilador no ve ningún código que pueda producir throw una excepción de C++.

Control de excepciones estructurado y estándar de C++

La opción del compilador /EHa permite el desenredado seguro de la pila tanto para las excepciones asincrónicas como para las excepciones de C++. Admite el control de las excepciones estándar de C++ y de las estructuradas mediante el uso de la cláusula nativa de C++ catch(...). Para implementar SEH sin especificar /EHa, puede usar la sintaxis __try, __except y __finally. Para más información, consulte Control de excepciones estructurado.

Importante

Especificar /EHa e intentar controlar todas las excepciones mediante catch(...) puede ser peligroso. En la mayoría de los casos, las excepciones asincrónicas son irrecuperables y podrían considerarse fatales. La detección y continuidad de estas excepciones puede dañar el proceso y generar errores que son difíciles de encontrar y corregir.

Aunque Windows y Visual C++ admiten SEH SEH, se recomienda encarecidamente que use el control de excepciones de C++, que se ajusta a la norma ISO (/EHsc o /EHs). Hace que el código sea más portable y flexible. Es posible que todavía haya ocasiones en las que tenga que usar SEH en código heredado o para determinados tipos de programas. Es necesario que el código compilado admita Common Language Runtime (/clr), por ejemplo. Para más información, consulte Control de excepciones estructurado.

Se recomienda que nunca vincule los archivos objeto compilados con/EHa otros compilados mediante /EHs o /EHsc en el mismo módulo ejecutable. Si tiene que controlar una excepción asincrónica mediante /EHa en cualquier parte del módulo, use /EHa para compilar todo el código del módulo. Puede usar la sintaxis de control de excepciones estructuradas en el mismo módulo que el código que se compila mediante /EHs. Sin embargo, no se puede mezclar la SEH sintaxis con C++ try, throw y catch en la misma función.

Use /EHa si desea detectar catch una excepción producida por un método distinto de throw. En este ejemplo se genera y se detecta una excepción estructurada:

// compiler_options_EHA.cpp
// compile with: /EHa
#include <iostream>
#include <excpt.h>
using namespace std;

void fail()
{
    // generates SE and attempts to catch it using catch(...)
    try
    {
        int i = 0, j = 1;
        j /= i;   // This will throw a SE (divide by zero).
        printf("%d", j);
    }
    catch(...)
    {
        // catch block will only be executed under /EHa
        cout << "Caught an exception in catch(...)." << endl;
    }
}

int main()
{
    __try
    {
        fail();
    }

    // __except will only catch an exception here
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // if the exception was not caught by the catch(...) inside fail()
        cout << "An exception was caught in __except." << endl;
    }
}

Control de excepciones en /clr

La opción /clr implica /EHa (es decir, /clr /EHa es redundante). El compilador genera un error si /EHs o /EHsc se usa después de /clr. Las optimizaciones no afectan a este comportamiento. Cuando se detecta una excepción, el compilador invoca los destructores de la clase para cualquier objeto que esté en el mismo ámbito que la excepción. Si no se detecta una excepción, estos destructores no se ejecutan.

Para obtener más información sobre las restricciones del control de excepciones en /clr, consulte _set_se_translator.

Comprobaciones de las excepciones en tiempo de ejecución

La opción /EHr fuerza las comprobaciones de terminación en tiempo de ejecución en todas las funciones que tienen un atributo noexcept. De forma predeterminada, las comprobaciones en tiempo de ejecución se pueden optimizar si el back-end del compilador determina que una función solo llama a funciones que no inician . Dichas funciones se componen de cualquier función que tiene un atributo que especifica que no se puede producir ninguna excepción. Esto incluye las funciones marcadas como noexcept, throw(), __declspec(nothrow) y cuando/EHc se especifica las funciones extern "C". Las funciones que no producen excepciones también incluyen aquellas funciones que el compilador ha determinado que no producen excepciones durante la inspección. Se puede establecer explícitamente el valor predeterminado mediante /EHr-.

Un atributo que no inicia no es una garantía de que una función no pueda producir excepciones. A diferencia del comportamiento de una noexcept función, el compilador de MSVC considera una excepción producida por una función declarada mediante throw(), __declspec(nothrow)o extern "C" como comportamiento indefinido. Las funciones que usan estos tres atributos de la declaración no imponen comprobaciones de terminación en tiempo de ejecución para las excepciones. Se puede usar la opción /EHr para ayudar a identificar este comportamiento indefinido, al forzar al compilador para que genere las comprobaciones en tiempo de ejecución para las excepciones no controladas que eluden una función noexcept.

Establecer la opción en Visual Studio o mediante programación

Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio

  1. Abra el cuadro de diálogo Páginas de propiedades del proyecto. Para más información, vea Establecimiento del compilador de C++ y de propiedades de compilación en Visual Studio.

  2. Seleccione Propiedades de configuración>C/C++>Generación de código.

  3. Modifique la propiedad Habilitar excepciones de C++ .

    O bien, establezca Habilitar excepciones de C++ en Noy, en la página de propiedades Línea de comandos , en el cuadro Opciones adicionales , agregue la opción del compilador.

Para establecer esta opción del compilador mediante programación

Consulte también

Opciones del compilador de MSVC
Sintaxis de la línea de comandos del compilador MSVC
Controlar errores y excepciones
Especificaciones de excepciones (throw)
Structured Exception Handling (C/C++)