My project contains shared library and exe client. I found that my own exception class thrown from the library is not caught by client catch block, and program terminates with "terminate called after throwing an instance of ..." message. Continuing to play with the project, I found that any exception of any type is not caught. For example, this catch doesn't work:
try
{
m_pSerialPort = new boost::asio::serial_port(m_IoService, "non-existing-port");
}
catch(const boost::system::system_error& e)
{
// ...
}
Error message:
terminate called after throwing an instance of
'boost::exception_detail::clone_impl
<boost::exception_detail::error_info_injector
<boost::system::system_error> >'
what(): No such file or directory
GCC version is 4.4.1, Linux OS. The same code is running successfully in Windows, MSVC.
What reason can prevent GCC program to catch exceptions properly?
Both the client .exe and the shared library should to be linked with libgcc in order to throw across shared library boundaries. Per the GCC manual:
... 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.
Related
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.
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.
I am building a shared library which uses Boost.thread internally. As a result, Boost.system is also used since Boost.thread depends on that. My shared library exports a C interface, so I want to hide all my internal exception handling and thread usage etc from the end user. It is supposed to be a black box so to speak. However, when I link with a client application, while the program runs fine - as soon as it is time to stop the processing by invoking a library function I get:
terminate called after throwing an instance of 'boost::thread_interrupted'
I catch this exception internally in the library, so I have no idea why it is not actually being caught. The end user's program is not meant to know about or handle Boost exceptions in any way. When building the shared library, I use static linking for both Boost.thread and Boost.system so the outside world is never meant to see them. I am on GCC 4.7 on Ubuntu 12. On Windows, I have no such problems (neither with MSVC or MinGw).
(EDIT)
I am editing the question to show a minimalistic example that reproduces the problem, as per the requests in the comments.
Here first is the code for testlib.cpp and testlib.h.
testlib.cpp:
#include <boost/thread/thread.hpp>
void thread_func()
{
while(1)
{
boost::this_thread::interruption_point();
}
}
void do_processing()
{
// Start a thread that will execute the function above.
boost::thread worker(thread_func);
// We assume the thread started properly for the purposes of this example.
// Now let's interrupt the thread.
worker.interrupt();
// And now let's wait for it to finish.
worker.join();
}
And now testlib.h:
#ifndef TESTLIB_H
#define TESTLIB_H
void do_processing();
#endif
I build this into a shared library with the following command:
g++ -static-libgcc -static -s -DNDEBUG -I /usr/boost_1_54_0 -L /usr/boost_1_54_0/stage/lib -Wall -shared -fPIC -o libtestlib.so testlib.cpp -lboost_thread -lboost_system -lpthread -O3
Then, I have the code for a trivial client program which looks as follows:
#include "testlib.h"
#include <cstdio>
int main()
{
do_processing();
printf("Execution completed properly.\n");
return 0;
}
I build the client as follows:
g++ -DNDEBUG -I /usr/boost_1_54_0 -L ./ -Wall -o client client.cpp -ltestlib -O3
When I run the client, I get:
terminate called after throwing an instance of 'boost::thread_interrupted'
Aborted (core dumped)
I am not explicitly catching the thread interruption exception, but according to the Boost documentation Boost.thread does that and terminates the given thread only. I tried explicitly catching the exception from within the thread_func function, but that made no difference.
(End OF EDIT)
(EDIT 2)
It is worth noting that even with -fexceptions turned on, the problem still persists. Also, I tried to throw and catch an exception that is defined in the same translation unit as the code that catches and throws it, with no improvement. In short, all exceptions appear to remain uncaught in the shared library even though I definitely have catch handlers for them. When I compile the client file and the testlib file as part of a single program, that is to say without making testlib into a shared library, everything works as expected.
(End OF EDIT 2)
Any tips?
I finally figured it out. The -static flag should never be specified when -shared is specified. My belief was that it merely told the linker to prefer static versions of libraries that it links, but instead it makes the generated dynamic library unsuitable for dynamic linking which is a bit ironic. But there it is. Removing -static solved all my problems, and I am able to link Boost statically just fine inside my dynamic library which handles exceptions perfectly.
Maybe this?
If you have a library L which throws E, then both L and the
application A MUST be linked against X, the library containing the
definition of E.
Try to link executable against boost, too.
A shared library that itself includes statically linked libraries is not such a good idea, and I don't think that this scenario is well supported in the GNU toolchain.
I think that your particular problem arises from the option -static-libgcc, but I've been unable to compile it in my machine with your options. Not that linking statically-dinamically to libpthread.so sounds as such a good idea either... What will happen if the main executable wants to create its own threads? Will it be compiled with -pthread? If it is, then you will link twice the thread functions; if it isn't, it will have the functions but not the precompiler macros nor the thread-safe library functions.
My advice is simply not to compile your library statically, that's just not the Linux way.
Actually that should not be a real problem, even if you don't want to rely on the distribution version of boost: compile your program against the shared boost libraries and deploy all these files (libboost_thread.so.1.54.0, libboost_system.so.1.54.0 and libtestlib.so) to the same directory. Then run your program with LD_LIBRARY_PATH=<path-to-so-files>. Since the client is not intended to use boost directly, it doesn't need the boost headers, nor link them in the compiler command. You still have your black box, but now it is formed by 3 *so files, instead of just 1.
I have a C++ library which I'm trying to get running on Mac OS X with Clang. The library consists of a DLL and a Unit-Test executable. It compiles fine with GCC and MSVC, with GCC, I use the following settings:
The library is compiled with -fvisibility=hidden
All exposed classes are explicitly marked as __attribute__(visibility("default"))
The library has some exception classes, derived from std::runtime_error. All such classes are marked for default visibility. There is a root class LibraryException from which more specific exceptions are derived.
On GCC, I use -std=c++0x, with clang, both the library and the unit test executable is built with -stdlib=libc++ -std=c++11
On Mac OS X, the unit test framework now fails, because exceptions are of the wrong type. I.e. a test like this fails:
// bla.foo () throws CustomException, which is derived from LibraryException
TEST_THROWS (bla.foo (), CustomException)
// This works however
TEST_THROWS (bla.foo (), LibraryException)
I verified that the typeinfo and vtable of my custom exception classes is exported using nm -g library.dylib | c++filt -p -i. This seems to be the case for all exceptions ... what the heck is going on here? I have tried to debug on the of the errors, and I see how the correct type is being thrown in the library and yet the same type cannot be caught in the unit test executable. Is there something special required with Clang to get this working? I'm using the latest googletest framework from SVN for testing.
A small test program exhibits the same problem:
try {
funcThatThrowsCustomExceptionFromLibraryDylib ();
} catch (CustomException& e) {
// doesn't get here
} catch (LibraryException& e) {
// does get here
// after demangle, this prints CustomException
// Can cast down to CustomException and access the fields as well
std::cout << typeid (e).name () << "\n";
}
It also fails for instance when a boost::lexical_cast exception is thrown from the Library.
Here is the correct solution:
When applying the visibility attribute, it must be applied both when the library is compiled as well when it is consumed. Otherwise, the client will not see the classes. For boost::lexical_cast, this means you have to use
#pragma GCC visibility push(default)
#include <boost/lexical_cast.hpp>
#pragma GCC visibility pop
until they get it fixed in the library by adding a __attribute((visibility("default"))) to the exception (as of Boost 1.50, the attribute is present, but it seems that the support for Clang is not there yet). When using it in a header in the library, so it can be properly caught in the client code. This #pragma also works with Clang.
The fact that specifying a throw () destructor helped was some luck, but it's definitely not the right fix.
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(...)