Bewerken

Share via


/EH (Exception handling model)

Specifies the exception handling model support generated by the compiler. Arguments specify whether to apply catch(...) syntax to both structured and standard C++ exceptions, whether extern "C" code is assumed to throw exceptions, and whether to optimize away certain noexcept checks.

Syntax

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

Arguments

a
Enables standard C++ stack unwinding. Catches both structured (asynchronous) and standard C++ (synchronous) exceptions when you use catch(...) syntax. /EHa overrides both /EHs and /EHc arguments.

s
Enables standard C++ stack unwinding. Catches only standard C++ exceptions when you use catch(...) syntax. Unless /EHc is also specified, the compiler assumes that functions declared as extern "C" may throw a C++ exception.

c
When used with /EHs, the compiler assumes that functions declared as extern "C" never throw a C++ exception. It has no effect when used with /EHa (that is, /EHca is equivalent to /EHa). /EHc is ignored if /EHs or /EHa aren't specified.

r
Tells the compiler to always generate runtime termination checks for all noexcept functions. By default, runtime checks for noexcept may be optimized away if the compiler determines the function calls only non-throwing functions. This option gives strict C++ conformance at the cost of some extra code. /EHr is ignored if /EHs or /EHa aren't specified.

-
Clears the previous option argument. For example, /EHsc- is interpreted as /EHs /EHc-, and is equivalent to /EHs.

/EH arguments may be specified separately or combined, in any order. If more than one instance of the same argument is specified, the last one overrides any earlier ones. For example, /EHr- /EHc /EHs is the same as /EHscr-, and /EHscr- /EHr has the same effect as /EHscr.

Remarks

Default exception handling behavior

The compiler always generates code that supports asynchronous structured exception handling (SEH). By default (that is, if no /EHsc, /EHs, or /EHa option is specified), the compiler supports SEH handlers in the native C++ catch(...) clause. However, it also generates code that only partially supports C++ exceptions. The default exception unwinding code doesn't destroy automatic C++ objects outside of try blocks that go out of scope because of an exception. Resource leaks and undefined behavior may result when a C++ exception is thrown.

Standard C++ exception handling

Full compiler support for the Standard C++ exception handling model that safely unwinds stack objects requires /EHsc (recommended), /EHs, or /EHa.

If you use /EHs or /EHsc, then your catch(...) clauses don't catch asynchronous structured exceptions. Any access violations and managed System.Exception exceptions go uncaught. And, objects in scope when an asynchronous exception occurs aren't destroyed, even if the code handles the asynchronous exception. This behavior is an argument for leaving structured exceptions unhandled. Instead, consider these exceptions fatal.

When you use /EHs or /EHsc, the compiler assumes that exceptions can only occur at a throw statement or at a function call. This assumption allows the compiler to eliminate code for tracking the lifetime of many unwindable objects, which can significantly reduce code size. If you use /EHa, your executable image may be larger and slower, because the compiler doesn't optimize try blocks as aggressively. It also leaves in exception filters that automatically clean up local objects, even if the compiler doesn't see any code that can throw a C++ exception.

Structured and standard C++ exception handling

The /EHa compiler option enables safe stack unwinding for both asynchronous exceptions and C++ exceptions. It supports handling of both standard C++ and structured exceptions by using the native C++ catch(...) clause. To implement SEH without specifying /EHa, you may use the __try, __except, and __finally syntax. For more information, see Structured exception handling.

Important

Specifying /EHa and trying to handle all exceptions by using catch(...) can be dangerous. In most cases, asynchronous exceptions are unrecoverable and should be considered fatal. Catching them and proceeding can cause process corruption and lead to bugs that are hard to find and fix.

Even though Windows and Visual C++ support SEH, we strongly recommend that you use ISO-standard C++ exception handling (/EHsc or /EHs). It makes your code more portable and flexible. There may still be times you have to use SEH in legacy code or for particular kinds of programs. It's required in code compiled to support the common language runtime (/clr), for example. For more information, see Structured exception handling.

We recommend that you never link object files compiled using /EHa to ones compiled using /EHs or /EHsc in the same executable module. If you have to handle an asynchronous exception by using /EHa anywhere in your module, use /EHa to compile all the code in the module. You can use structured exception handling syntax in the same module as code that's compiled by using /EHs. However, you can't mix the SEH syntax with C++ try, throw, and catch in the same function.

Use /EHa if you want to catch an exception that's raised by something other than a throw. This example generates and catches a structured exception:

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

Exception handling under /clr

The /clr option implies /EHa (that is, /clr /EHa is redundant). The compiler generates an error if /EHs or /EHsc is used after /clr. Optimizations don't affect this behavior. When an exception is caught, the compiler invokes the class destructors for any objects that are in the same scope as the exception. If an exception isn't caught, those destructors aren't run.

For information about exception handling restrictions under /clr, see _set_se_translator.

Runtime exception checks

The /EHr option forces runtime termination checks in all functions that have a noexcept attribute. By default, runtime checks may be optimized away if the compiler back-end determines that a function only calls non-throwing functions. Non-throwing functions are any functions that have an attribute that specifies no exceptions may be thrown. They include functions marked noexcept, throw(), __declspec(nothrow), and, when /EHc is specified, extern "C" functions. Non-throwing functions also include any that the compiler has determined are non-throwing by inspection. You can explicitly set the default behavior by using /EHr-.

A non-throwing attribute isn't a guarantee that exceptions can't be thrown by a function. Unlike the behavior of a noexcept function, the MSVC compiler considers an exception thrown by a function declared using throw(), __declspec(nothrow), or extern "C" as undefined behavior. Functions that use these three declaration attributes don't enforce runtime termination checks for exceptions. You can use the /EHr option to help you identify this undefined behavior, by forcing the compiler to generate runtime checks for unhandled exceptions that escape a noexcept function.

Set the option in Visual Studio or programmatically

To set this compiler option in the Visual Studio development environment

  1. Open the project's Property Pages dialog box. For details, see Set C++ compiler and build properties in Visual Studio.

  2. Select Configuration Properties > C/C++ > Code Generation.

  3. Modify the Enable C++ Exceptions property.

    Or, set Enable C++ Exceptions to No, and then on the Command Line property page, in the Additional Options box, add the compiler option.

To set this compiler option programmatically

See also

MSVC Compiler options
MSVC Compiler command-line syntax
Errors and exception handling
Exception specifications (throw)
Structured Exception Handling (C/C++)