Visual C++ Unmanaged Code: Use /EHa or /EHsc for C++ exceptions?
Asked Answered
J

2

22

If I'm creating a new project in unmanaged C++, Visual Studio 2008 or greater, which exception handling model do I want to go with?

I understand that /EHa option results in less efficient code, and also catches SEH exceptions, right?

So I have been steering clear of that option and typically going with /EHsc, so that I'm only catching C++ exceptions that are actually thrown and not catching access violations and other structured execptions, in catch(...) handlers. If there is an access violation in my code, I don't want it being masked by a catch(...) {}.

I code with others who want catch(...) {} to do nothing and they even want it to do it if there is an access violation, which seems like a really bad idea to me. If there is a bug due to bad coding, you don't want to stick your fingers in your ears and loudly say "La la la la la!" so that you don't have to have the program crash? In fact, if the code is now in a bad state because of a coding error, do you really want the code to continue?

So my general thought is that /EHa creates larger/slower code and it allows programmers to get away with writing code that if a fatal bug is present, it will continue to run in an undefined state.

BTW, I'm talking about applications and service code which is what we are writing for the most part. Not low level device drivers or anything like that.

Please weigh in with your thoughts.

Jube answered 10/12, 2010 at 22:52 Comment(0)
O
23

/EHa does two things. First and foremost, it suppresses an optimization that omits exception filters that automatically call the destructors of local class variables if the code analyzer cannot see any code that might throw a C++ exception. This makes stack unwinding safe for any kind of exception, not just a C++ exception. Overhead for these exception filters is time on x86 and space on both x86 and x64.

And yes, it alters the behavior of catch(...), it now also filters any SEH exception, not just C++. This is indeed a gamble because you catch all the really nasty stuff, the asynchronous hardware exceptions. Although I personally don't think that catching all C++ exceptions is very defensible either, you still have but a vague idea to what degree the program state got mutated and why it failed.

Realistically, you'll need to switch to using __try/__except so that you can write your own exception filter and avoid catching the bad ones. The exception code for C++ exceptions is 0xe04d5343 ("MSC"). Using _set_se_translator() would be another approach.

Oba answered 11/12, 2010 at 7:25 Comment(2)
Great answer, can you further elaborate on the Overhead for these exception filters is time on x86 and space on both x86 and x64. part? More specifically, why no time overhead on x64?Minuscule
x64 uses a lookup table to map the exception address to a catch handler, that table is built at compile time. x86 pushes the handler address on the stack at the try block entry.Oba
N
7

I use /EHa because it's safe with .NET interop , whereas /EHsc may not be; see Destructors not called when native (C++) exception propagates to CLR component for example.

However, if for a specific bit of code the extra performance really matters and you don't need .NET (or whatever else) compatibility, then sure, /EHsc sounds fine.

Neither /EHsc nor /EHa catch most memory errors, so using these to catch access violations is a hopeless case.

Nickola answered 10/12, 2010 at 23:1 Comment(6)
You should never try to catch access violations in any case.Dor
That's my understanding... but I have people writing catch(...){} and if /EHa is selected, then that would bury the access violation I believe. It's one thing to catch(...) { cleanup_stuff; throw; } but even in that case, if it's an access violation that's being caught, are you sure the cleanup_stuff is going to do it's job? You're in a bad state, so I would probably think the program is best off just crashing there.Jube
I'm working on a client/server system where if the server has an exception (ideally, any exception, including access violation), I would like to send the exception message to the client before allowing the server thread to crash. Otherwise, the server just stops responding.Hexachlorophene
EHa is definitely what you want for services etc where reliability is paramount. Talking about access violations makes the problem sound unlikely, but don't forget that divide by zero could take down your service!Principium
@NickWestgate totally agree, in high availability service, sometimes it's not hard to isolate less reliable part of code with proper interfacing and catch everything that's going wrong (including dividebyzero) behind that interface and still have a good idea about the program's state.Minuscule
Access violations are caught only by vectored handlers right?Sweeper

© 2022 - 2024 — McMap. All rights reserved.