What are the consequences of mixing exception handling models in Visual Studio 2010?
Asked Answered
C

2

7

I have third-party static library built with Enable C++ Exceptions set to No (/EH flag not specified). What are the consequences to calling into it from code built with C++ exceptions enabled (/EHa)? If a Structured Exception is thrown from within the library, will the function provided to _set_se_translator by the main application be reliably called? (My experiments show that it will, but just wondering if this is defined behavior).

Are there any other considerations when mixing /EH exception handing models?

Canotas answered 29/6, 2011 at 16:45 Comment(4)
Technically, the standard would say that causes undefined behavior for breaking ODR. I'm assuming you want a more concrete explanation, however (which is why this is a comment).Harcourt
@Billy ONeal: You hit UB as soon as you disable exceptions; mixing çan't make that worse. UB doesn't come in degrees.Shandy
@MSalters: Lol -- didn't even think of that. That's true.Harcourt
Yeah, I realize I'm in non-standard territory here. I'm just wondering if the Microsoft implementation has defined behavior in this situation.Canotas
H
5

Calling into code which does not have exceptions enabled shouldn't produce any problems -- this is no different than calling an external C function or something of that nature.

Calling from code which does not have exceptions enabled (into exception enabled code) will probably not contain the correct stack unwinding semantics in the exception disabled code, which means you'll be breaking invariants of that code, unless it was specifically designed to work with exceptions. (For example, some libraries (e.g. ANTLR) allocate all memory in a block and have the user code free everything at once, allowing exceptions to be used without leaking even though they themselves do not use exceptions).

Raymond Chen has quite an article about the innards of how C++'s exception handling works on MSVC++. Long story short, it's built on top of Windows' SEH. Therefore it should behave similarly to what happens if you throw a SEH exception in e.g. C code. (However, I've not verified this myself)

Harcourt answered 29/6, 2011 at 19:35 Comment(1)
All Windows questions lead back to Raymond Chen. :) Thanks!Canotas
P
5

According to the MSDN then one is allowed to mix /EHa and /EHsc:

The two exception handling models, synchronous and asynchronous, are fully compatible and can be mixed in the same application.

But there seems to an exception to this rule, and that is when passing exceptions from unmanaged (/EHsc) to managed (/clr). The managed codes catches all exceptions using structured exception handling (SEH), and this causes unmanaged destructors not to be called when unwinding the stack. There are different workarounds:

  1. Change the unmanaged code to use /EHa instead of /EHsc. This has the downside that catch(...) within unmanaged code suddenly will catch access violations and other crazy stuff.
  2. Create try-catch block within the unmanaged code, and ensure that no exceptions are passed between the unmanaged world and the managed world.

    2.1. Possible middle road is to ensure that no destructors are expected to be called when passing exception from unmanaged to managed world. Within the unmanaged code make a try-catch wrapper, and then in the catch-block rethrow the exception into the managed world.

Psychoneurosis answered 10/12, 2011 at 0:1 Comment(2)
Great answer for detailed explanation regarding managed unmanaged interaction. Can you also elaborate on why the destructors are not called in such case as the link has expired? I suppose when the exception catching side expects SEH style exception while the throw side uses C++ exception, the stack unwinding thunks become sort of "invisible" to the catch side?Cardwell
The docs seem to have changed since this answer was made "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 [...]". link to the sectionDuplication

© 2022 - 2024 — McMap. All rights reserved.