Re: Being Confused by /EH Exception Handling Model
On Sun, 7 Dec 2008 00:51:24 -0800 (PST), wuguangwen734@gmail.com wrote:
Recently,when I read about the exception handing model, the MSDN said
that compiling with /EHc tells compiler to assume that extern C
functions never throw a C++ exception. It demonstrates this with the
following example:
void f1(void) throw(int) {
printf_s("About to throw 1\n");
if (1)
throw 1;
}
// only valid if compiled without /EHc
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
f1();
}
int main() {
try {
f4();
}
catch(...) {
printf_s("Caught exception from f4\n");
}
}
I just compiled this example with /EHc option, and found the catch
handler can deal with a thrown exception from calling f4. I changed
the compiling option to /EHs and got the exactly same results.
Then, I registered my own terminate function by calling set_terminate
(),but nothing different happened.
I'm put into a state of confusion.
Interesting, /EHsc doesn't take effect in VC2008 unless I compile with
optimizations, e.g. /O1, and then the compiler optimizes the try/catch
machinery out of existence. OTOH, if I rewrite your program like this:
struct X
{
~X();
};
....
// Replace main with the following
void f()
{
X x;
f4();
}
Compiled with cl -EHsc -FAs -c a.cpp, i.e. without optimizing, the compiler
does /not/ perform the EH setup in f to ensure that x will be destroyed
should f exit via exception.
So, while /EHc does not suppress try/catch in unoptimized builds, it does
suppress EH setup for stack unwinding. I don't know that I would call this
a bug. I mean, when you tell the compiler to assume that extern "C"
functions don't throw, and then you create the opposite situation, you are
lying to the compiler. It appears that the elimination of try/catch
machinery is tied up in the optimizer, while the elimination of EH setup in
functions such as f is not. So, while you could report it at Connect, I
suspect MS would respond that /EHc is purely advisory for optimization
purposes, and it is user error for an extern "C" function to throw when
/EHc is in effect. That said, it is subtle, and the documentation could say
that /EHc doesn't necessarily prevent the compiler from catching exceptions
thrown by extern "C" functions. I would expect a try block that contains a
mixture of function calls like f4 and ordinary functions that throw to
catch f4's exception, as optimization won't suppress try/catch in that
case, but local objects associated solely with unwinding f4 would not be
destroyed.
--
Doug Harrison
Visual C++ MVP