Skip to content

Commit 5e896fb

Browse files
authored
Merge pull request #2817 from corob-msft/cr-2073
Fix 2073, clarify EH documentation
2 parents b125d48 + 4b4292c commit 5e896fb

File tree

2 files changed

+92
-52
lines changed

2 files changed

+92
-52
lines changed
Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,68 @@
11
---
2-
title: "/EH (Exception Handling Model)"
3-
ms.date: "08/14/2018"
2+
title: "/EH (Exception handling model)"
3+
description: "Reference guide to the Microsoft C++ /EH (Exception handling model) compiler options in Visual Studio."
4+
ms.date: "04/14/2020"
45
f1_keywords: ["VC.Project.VCCLWCECompilerTool.ExceptionHandling", "/eh", "VC.Project.VCCLCompilerTool.ExceptionHandling"]
56
helpviewer_keywords: ["exception handling, compiler model", "cl.exe compiler, exception handling", "EH compiler option [C++]", "-EH compiler option [C++]", "/EH compiler option [C++]"]
7+
no-loc: [SEH, try, catch, throw, extern, finally, noexcept]
68
ms.assetid: 754b916f-d206-4472-b55a-b6f1b0f2cb4d
79
---
8-
# /EH (Exception Handling Model)
10+
# /EH (Exception handling model)
911

10-
Specifies the kind of exception handling used by the compiler, when to optimize away exception checks, and whether to destroy C++ objects that go out of scope because of an exception. If **/EH** is not specified, the compiler enables your code to catch both asynchronous structured exceptions and C++ exceptions, but does not destroy C++ objects that go out of scope because of an asynchronous exception.
12+
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.
1113

1214
## Syntax
1315

14-
> **/EH**{**s**|**a**}[**c**][**r**][**-**]
16+
> **`/EHa`**[**`-`**]\
17+
> **`/EHs`**[**`-`**]\
18+
> **`/EHc`**[**`-`**]\
19+
> **`/EHr`**[**`-`**]
1520
1621
## Arguments
1722

18-
**a**<br/>
19-
The exception-handling model that catches both asynchronous (structured) and synchronous (C++) exceptions by use of C++ `catch(...)` syntax.
23+
**`a`**\
24+
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.
2025

21-
**s**<br/>
22-
The exception-handling model that catches synchronous (C++) exceptions only and tells the compiler to assume that functions declared as **extern "C"** may throw an exception.
26+
**`s`**\
27+
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.
2328

24-
**c**<br/>
25-
If used with **s** (**/EHsc**), catches C++ exceptions only and tells the compiler to assume that functions declared as **extern "C"** never throw a C++ exception. **/EHca** is equivalent to **/EHa**.
29+
**`c`**\
30+
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.
2631

27-
**r**<br/>
28-
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.
32+
**`r`**\
33+
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.
34+
35+
**`-`**\
36+
Clears the previous option argument. For example, **`/EHsc-`** is interpreted as **`/EHs /EHc-`**, and is equivalent to **`/EHs`**.
37+
38+
**`/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`**.
2939

3040
## Remarks
3141

32-
The **/EHa** compiler option is used to support asynchronous structured exception handling (SEH) with the native C++ `catch(...)` clause. To implement SEH without specifying **/EHa**, you may use the **__try**, **__except**, and **__finally** syntax. Although Windows and Visual C++ support SEH, we strongly recommend that you use ISO-standard C++ exception handling (**/EHs** or **/EHsc**) because it makes code more portable and flexible. Nevertheless, in existing code or for particular kinds of programs—for example, in code compiled to support the common language runtime ([/clr (Common Language Runtime Compilation)](clr-common-language-runtime-compilation.md))—you still might have to use SEH. For more information, see [Structured Exception Handling (C/C++)](../../cpp/structured-exception-handling-c-cpp.md).
42+
### Default exception handling behavior
43+
44+
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](../../cpp/try-throw-and-catch-statements-cpp.md) blocks that go out of scope because of an exception. Resource leaks and undefined behavior may result when a C++ exception is thrown.
45+
46+
### Standard C++ exception handling
47+
48+
Full compiler support for the Standard C++ exception handling model that safely unwinds stack objects requires **`/EHsc`** (recommended), **`/EHs`**, or **`/EHa`**.
3349

34-
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.
50+
If you use **`/EHs`** or **`/EHsc`**, then your `catch(...)` clauses don't catch asynchronous structured exceptions. Any access violations and managed <xref:System.Exception?displayProperty=fullName> 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.
3551

36-
If you use **/EHs** or **/EHsc**, then your `catch(...)` clause does not catch asynchronous structured exceptions. Access violations and managed <xref:System.Exception?displayProperty=fullName> exceptions are not caught, and objects in scope when an asynchronous exception is generated are not destroyed even if the asynchronous exception is handled.
52+
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.
3753

38-
If you use **/EHa**, the image may be larger and might perform less well because the compiler does not optimize a **try** block as aggressively. It also leaves in exception filters that automatically call the destructors of all local objects even if the compiler does not see any code that can throw a C++ exception. This enables safe stack unwinding for asynchronous exceptions as well as for C++ exceptions. When you use **/EHs**, the compiler assumes that exceptions can only occur at a **throw** statement or at a function call. This allows the compiler to eliminate code for tracking the lifetime of many unwindable objects, and this can significantly reduce code size.
54+
### Structured and standard C++ exception handling
3955

40-
We recommend that you not link objects compiled by using **/EHa** together with objects compiled by 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**, but you can't mix the SEH syntax with **try**, **throw**, and **catch** in the same function.
56+
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](../../cpp/structured-exception-handling-c-cpp.md).
4157

42-
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:
58+
> [!IMPORTANT]
59+
> 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.
60+
>
61+
> 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](clr-common-language-runtime-compilation.md)), for example. For more information, see [Structured exception handling](../../cpp/structured-exception-handling-c-cpp.md).
62+
>
63+
> 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.
64+
65+
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:
4366

4467
```cpp
4568
// compiler_options_EHA.cpp
@@ -48,39 +71,51 @@ Use **/EHa** if you want to catch an exception that's raised by something other
4871
#include <excpt.h>
4972
using namespace std;
5073

51-
void fail() { // generates SE and attempts to catch it using catch(...)
52-
try {
53-
int i = 0, j = 1;
54-
j /= i; // This will throw a SE (divide by zero).
55-
printf("%d", j);
56-
}
57-
catch(...) { // catch block will only be executed under /EHa
58-
cout<<"Caught an exception in catch(...)."<<endl;
59-
}
74+
void fail()
75+
{
76+
// generates SE and attempts to catch it using catch(...)
77+
try
78+
{
79+
int i = 0, j = 1;
80+
j /= i; // This will throw a SE (divide by zero).
81+
printf("%d", j);
82+
}
83+
catch(...)
84+
{
85+
// catch block will only be executed under /EHa
86+
cout << "Caught an exception in catch(...)." << endl;
87+
}
6088
}
6189

62-
int main() {
63-
__try {
64-
fail();
65-
}
66-
67-
// __except will only catch an exception here
68-
__except(EXCEPTION_EXECUTE_HANDLER) {
69-
// if the exception was not caught by the catch(...) inside fail()
70-
cout << "An exception was caught in __except." << endl;
71-
}
90+
int main()
91+
{
92+
__try
93+
{
94+
fail();
95+
}
96+
97+
// __except will only catch an exception here
98+
__except(EXCEPTION_EXECUTE_HANDLER)
99+
{
100+
// if the exception was not caught by the catch(...) inside fail()
101+
cout << "An exception was caught in __except." << endl;
102+
}
72103
}
73104
```
74105

75-
The **/EHc** option requires that **/EHs** or **/EHa** is specified. 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 do not affect this behavior. When an exception is caught, the compiler invokes the class destructor or destructors for the object or objects that are in the same scope as the exception. When an exception is not caught, those destructors are not run.
106+
### Exception handling under /clr
107+
108+
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.
109+
110+
For information about exception handling restrictions under **`/clr`**, see [_set_se_translator](../../c-runtime-library/reference/set-se-translator.md).
76111

77-
For information about exception handling restrictions under **/clr**, see [_set_se_translator](../../c-runtime-library/reference/set-se-translator.md).
112+
### Runtime exception checks
78113

79-
The option can be cleared by using the symbol **-**. For example, **/EHsc-** is interpreted as **/EHs** **/EHc-** and is equivalent to **/EHs**.
114+
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-`**.
80115

81-
The **/EHr** compiler 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. This includes 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 by using **/EHr-**.
116+
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.
82117

83-
However, the non-throwing attribute is not a guarantee that no exceptions can 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 do not 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.
118+
## Set the option in Visual Studio or programmatically
84119

85120
### To set this compiler option in the Visual Studio development environment
86121

@@ -98,8 +133,8 @@ However, the non-throwing attribute is not a guarantee that no exceptions can be
98133

99134
## See also
100135

101-
[MSVC Compiler Options](compiler-options.md)<br/>
102-
[MSVC Compiler Command-Line Syntax](compiler-command-line-syntax.md)<br/>
103-
[Errors and Exception Handling](../../cpp/errors-and-exception-handling-modern-cpp.md)<br/>
104-
[Exception Specifications (throw)](../../cpp/exception-specifications-throw-cpp.md)<br/>
136+
[MSVC Compiler Options](compiler-options.md)\
137+
[MSVC Compiler Command-Line Syntax](compiler-command-line-syntax.md)\
138+
[Errors and Exception Handling](../../cpp/errors-and-exception-handling-modern-cpp.md)\
139+
[Exception Specifications (throw)](../../cpp/exception-specifications-throw-cpp.md)\
105140
[Structured Exception Handling (C/C++)](../../cpp/structured-exception-handling-c-cpp.md)

0 commit comments

Comments
 (0)