using _set_se_translator and compilation flags - c++

Documentation states that "You must use /EHa when using _set_se_translator.".
My question is: should /EHa be used for all files in project/ all files in project that catch exceptions or just in the file that calls _set_se_translator ?

You need it not just for functions that catch exceptions, but also functions that throw and propagate them. The actual call to _set_se_translator itself probably doesn't need to be compiled with /Eha, but why be inconsistent?

After checking I must disagree with what has been said before about all instances needed to be compiled with /EHa. I made a small program with:
crashing code
__declspec(dllexport) void crashMe() { *((int*)0)=0; }
in a DLL compiled without any exception handling at all
calling code elsewhere in a try/catch
Then
Unless the calling code is compiled with /EHa the program will crash
Without _set_se_translator the exception can only be caught in catch(...)

Related

Enforce Visual Studio exception handling mode

I'm using the Visual Studio /EHsc exception handling mode in my project. This means catch(...) won't catch structured exceptions. I've got a public header that does a catch(...) that can be included by consumer projects.
I'm concerned that a project consuming my header may have a different exception handling mode that will make my header misbehave.
Is there a way of static_asserting or #pragma error'ing or otherwise failing the build if the exception handling mode isn't as needed?
See: https://msdn.microsoft.com/en-us/library/1deeycx5.aspx
From https://msdn.microsoft.com/en-us/library/b0084kay.aspx
_CPPUNWIND Defined as 1 if one or more of the /GX (Enable Exception Handling), /clr (Common Language Runtime Compilation), or /EH
(Exception Handling Model) compiler options are set. Otherwise,
undefined.
It's not perfect, but it gives you a fighting chance to get them the same

C++ exceptions and the .eh_frame ELF section

Is it that the absence or damage of the .eh_frame ELF section is the cause of exceptions in my C++ code stopped working? Any exception that previously was caught successfully is now calling std::terminate().
My situation:
My zzz.so shared library has try-catch blocks:
try {
throw Exc();
} catch (const Exc &e) {
LOG("ok " << e.what());
} catch (...) {
LOG("all");
}
An executable which loads the zzz.so (using ldopen). It call a function in the zzz.so
All the exceptions thrown in the zzz.so are successfully caught inside zzz.so and dumped into my log file
There is another aaa.so that is loaded into another binary. That another aaa.so is loading my zzz.so.
All the same exceptions thrown in the zzz.so lead to call std::terminate().
How is that possible?
update
I don't know HOW is that possible still, but Clang 3.3 (FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610) solved the problem.
How is that possible?
When an exception is thrown, control passes to __cxa_throw routine (usually in libstdc++.so), which is then responsible for finding the catch clause and calling destructors along the way, or calling std::terminate if no catch is found.
The answer then is most likely that the first executable (the one where exceptions work) uses libstdc++.so that is capable of decoding .eh_frame in your library, while the second application (the one where exceptions do not work), either uses an older (incompatible) version of libstdc++.so, or links against libstdc++.a, or something along these lines.
Note: the actual work of raising the exception is done by _Unwind_RaiseException in libgcc_s.so.1, so even if both applications use the same libstdc++.so, they may still use different libgcc.
Update:
Will I benefit from static linking libstdc++ and libgcc into my .so library?
Maybe. TL;DR: it's complicated.
There are a few things to consider:
On any platform other than i386, you would have to build your own copy of libstdc++.a and libgcc.a with -fPIC before you can link them into your zzz.so. Normally these libraries are built without -fPIC, and can't be statically linked into any .so.
Static linking of libstdc++.a into your zzz.so may make it a derived work, and subject to GPL (consult your lawyer).
Even when there is a _Unwind_RaiseException exported from zzz.so, normally there will already be another instance of _Unwind_RaiseException defined in (loaded earlier) libgcc_s.so, and that earlier instance is the one that will be called, rendering your workaround ineffective. To make sure that your copy of _Unwind_RaiseException is called, you would need to link zzz.so with -Bsymbolic, or with a special linker script to make all calls to _Unwind_RaiseException (and everything else from libgcc.a) internal.
Your workaround may fix the problem for zzz.so, but may cause a problem for unrelated yyy.so that is loaded even later, and that wants the system-provided _Unwind_RaiseException, not the one from zzz.so. This is another argument for hiding all libgcc.a symbols and making them internal to zzz.so.
So the short answer is: such workaround is somewhat likely to cause you a lot of pain.

catch (...) across shared library boundary on gcc mingw

I am a Windows developer with some knowledge of C++ EH and SEH implementation in VC++ but new to MinGW. I have built an open source application on MinGW where a dll throws a C++ exception and a client .exe catches it with two catch clauses. One catch clause is "catch (std::exception &e)" and the subsequent one is "catch(...)".
My application terminates with a call to abort despite the latter catch handler.
From searching the web, I understand that gcc exception handling uses pointer comparison to determine whether that type of a thrown exception matches a catch clause. Which can cause problems if the RTTI type descriptor instance used in the throwing and the catching modules differ. In VC++ a catch handler with ellipsis type ("catch (...)") does not do any type matching. However, for my mingw application the ellipsis catch is not determined as handling the thrown exception. I tried to set a breakpoint on ___gxx_personality_v0 to debug this but gdb says that symbol is undefined even though "nm executable.exe" built with debugging shows the symbol as defined.
Any ideas about how "catch (...)" is handled by the personality routine ? Any pointers on how to debug and/or fix this would be appreciated. I really would like the app to terminate cleanly without a popup saying "The application has requested to be terminated in an unusual way".
Thanks for any help,
--Patrick
Update: I found the solution in another post here about the same issue: Exceptions are not caught in GCC program . It turns out that both the dll and the executable were built with "-static-libgcc". Changing that to "-shared-libgcc" fixed the issue.
The quote from the gcc manual from the above post:
... if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ or GCJ driver, as appropriate for the languages used in the program, or using the option -shared-libgcc, such that it is linked with the shared libgcc.

How do I detect if my code is being compiled with -fno-exceptions?

I'm writing a C++ library and I would like to make my API throw exceptions for invalid parameters, but rely on asserts instead when the code is compiled with -fno-exceptions.
Is there a way to detect at compile-time if I'm allowed to use exception handling?
Note that I'm writing a header-only library, so I don't have a configure phase and I don't have access to the build system to simply define a macro on the command line (and
I don't want to add burden to the user).
Since the Standard doesn't have any concept of "-fno-exceptions", of course the solution could be compiler-dependent. In this case I'm interested in solutions that work with both g++ and clang++, other compilers are not important for this project.
Thank you very much
GCC and Clang define the __EXCEPTIONS macro when exceptions are enabled, and do not define it when exceptions are disabled via -fno-exceptions.
Example:
#include <cstdio>
int main() {
#ifdef __EXCEPTIONS
puts("Exceptions are enabled");
#else
puts("Exceptions are disabled");
#endif
}

Why is this exception not being caught across DLLs?

I have a DLL which throws an exception like so:
throw POMException(err, drvErr, errmsg);
The calling code is in a separate program, and has a try, catch block like so:
try
{
// function in separate DLL
}
catch (TXNPDO_Exception& e)
{
SR_PERFLOG_MSG(SR_PERFMASK_SELECT, "ERROR selectInStages");
TXNDBO_THROW(e);
}
Where TXNPDO_Exception is defined in an included file:
#define TXNPDO_Exception POMException
When running this in a debugger, it states that the POMException was unhandled. I even added a catch(...) clause and it still isn't handled.
I suspect that this has something to do with the Visual C++ compilation parameters, since the DLL library in question is a legacy library that is compiled separate to the program calling it. I am using Visual Studio 2003.
The DLL cpp files are compiled with the following (relevant) flags: /X /GR /Ob1 /Zi /GX /Od /MDd /LD. Other exceptions within the calling program are handled correctly.
Can anyone provide reasons why this exception isn't being propagated to the calling program?
Edit:
The DLL library was previously compiled with possible build environment and code changes that are not available to me. The previously compiled library propagates exceptions correctly.
I am compiling the client program using the same compiler, using mostly the same switches: -Od -W3 -Z7 -MDd -GX -GR -Zm800 (no /X or /Ob1 and /Z7 instead of /Zi).
I would assume that throwing exceptions across .dll boundaries could only be possible, when the various .dll and program executable are compiled against the same C++ runtime, thus sharing the same heap. I could be wrong, but this is my best guess.
Edit:
I guess I wasn't wrong.
I have finally figured out what the problem is, and in this particular case, it is nothing to do with throwing exceptions between DLLs.
The problem is occurring due to an exception handler hook being installed further up the call stack. I diagnosed this by adding try, catch(...) blocks to every level in the library until I found the point at which the exception wasn't propagated. When I commented out the exception handler hook registration code, the exception was successfully propagated.
I now have to figure out the workings of exception handler hooks, which is outside the scope of this question. Thanks to everyone who shared their answers.