Prevent gcc/libstdc++ from calling terminate on throwing from throw() method - c++

If I have a method marked throw(), e.g.
void method() throw()
{
// do some stuff, call other functions
}
and yet exception does happen inside, gcc will terminate the application (with message "terminate called after throwing an instance of 'xyz'").
Is there a way to avoid this behaviour?
For example, a command-line switch to ignore throw() stuff or force eh_frame generation. Etc.

Did you try the GCC manual?
-fno-enforce-eh-specs
Don't generate code to check for violation of exception specifications at run time. This option violates the C++ standard, but may be useful for reducing code size in production builds, much like defining `NDEBUG'. This does not give user code permission to throw exceptions in violation of the exception specifications; the compiler still optimizes based on the specifications, so throwing an unexpected exception results in undefined behavior at run time.
It doesn't force generate of EH frames, but it should stop the call to std::unexpected() and so might be useful for your case.
As the docs say, "the compiler still optimizes based on the specifications" so e.g. it doesn't help when the call to method() can be inlined into the catch site, because the compiler assumes the catch is not needed, because the empty exception spec says no exception will be throw, and so if an exception is thrown it doesn't get caught. If the call to method() is not inlinable into the catch site it seems to work, the exception leaves method() without calling std::unexpected() and can be caught higher up the stack.
Edit: This will still call std::terminate() even with -fno-enforce-eh-specs:
void func() throw() { throw ""; }
void func2() { func(); }
int main() { try { func2(); } catch (...) { } }
The compiler can see that the call to func2 only calls a no-throw function, so the catch will never be needed and so is optimised away. When the exception is thrown, it isn't caught.
This does work with -fno-enforce-eh-specs and doesn't terminate:
/* func2.cc */
void func() throw();
void func2() { func(); }
/* main.cc */
void func2();
int main() { try { func2(); } catch (...) { } }
Here, when compiling main.cc, the compiler can't tell whether func2 is going to throw or not because it has no exception specification and its definition is not visible in main.cc, so the catch cannot be omitted. When the exception is thrown it will be caught.

You can provide your own terminate handler by calling std::set_terminate ... however I don't think it's legal to return from there, so the only thing it can really do is terminate somehow.
You can provide your own unexpected exception handler with std::set_unexpected: the default one calls std::terminate but you can do something different (like logging and swallowing the exception). Whether or not you can recover usefully depends on your program though. Also, I've seen it marked deprecated, so relying on this probably isn't the greatest idea.

Related

How to destroy local variables if exceptions thrown by a function may be uncaught?

When a function throws while the exception is uncaught, stack unwinding is unlikely to trigger, so destructors of local variables won't be called. For example, the following code outputs only "created" (and the error messages) under g++ 7.1.0:
#include <iostream>
using namespace std;
struct A {
A() { cerr << "created\n"; }
~A() { cerr << "destroyed\n"; }
};
void f() {
A a;
throw 0;
}
int main() {
f();
}
This may lead to memory leaks upon crashing if A allocates memory, and whether the memory will be freed depends on the OS.
A possible solution I find is wrap f() in a function try-catch block:
void f() try {
A a;
throw 0;
} catch (...) {
throw;
}
In this way destructor of a is always called. However, I don't find it satisfying because an empty catch clause has to be written, and it's not straightforward.
So which of the following should be considered correct, or if there's better practice (especially when implementing a function in a library) ?
Wrap every potentially-throwing function with try-catch block mentioned above;
Pretend the callers to this function always catches the exception;
Because uncaught exception causes crashing, I don't have to destruct local variables.
Put a top-level try-catch(...) in your main function that outputs an error message and exits. This will ensure that unwinding always happens.
Though the question is why you would want that. If you're in any real-world non-embedded environment, the OS will clean up all resources of your process. There's no maybe about it. And since there are other ways for a process to crash which don't involve exceptions, you can't rely on destructors for cleanup in such a case anyway.
If you're in an embedded environment, the situation is similar. You don't have an OS to clean up, maybe, but crashes usually lead to a device reset, which has the same effect. And again, you can't rely on destructors because there are other ways to crash.

Is is possible in C++ to throw nothing?

Under exceptional circumstances, I want my program to stop processing, output an error to std::cerr, clean up, and exit.
However, calling exit() will not call all the destructors of any objects that have been constructed. I would like to have the destructors called nicely, so I wrapped all the code in a try-catch block, something like this:
int main(int argc, char** argv){
try {
bool something_is_not_right = false;
/* lots of variables declared here */
/* some code that might set something_is_not_right to true goes here */
if(something_is_not_right){
std::cerr << "something is not right!!!" << std::endl;
throw '\0'; // dummy unused variable for throwing.
}
}
catch (...) {}
return 0;
}
In this way, I get guaranteed destruction of all my variables. But I can't seem to find a way to get C++ to throw nothing. throw; has a special meaning in C++; it isn't throwing nothing.
Is there a way to throw nothing?
No
It's not possible to throw nothing. You need to throw something. While you may have seen people use the throw keyword without anything, this just means they are re-throwing the currently handled exception.
This is not a direct answer to your question, but a personal recommendation.
You might want to take a look at the predefined exceptions of stdexcept which cover almost any exceptional behaviour that occurs in a program. In your case I would throw a std::runtime_error. Also, only catch what you expect to be thrown and not catch 'em all. If you really want to catch everything, then catch std::exception (the base class of all standard exceptions).
In my opinion handling unknown exceptions doesn't really make sense and the only logical consequence is to just abort execution.
#include <iostream>
#include <stdexcept>
int main()
{
try
{
bool something_is_not_right = true;
if ( something_is_not_right )
throw std::runtime_error("something is not right!!!");
}
catch (std::runtime_error& e)
{
std::cerr << e.what() << '\n';
throw;
}
}
How do you know that the reason for the catch is your error or something else (out of memory is always a good one). If you detect an error, then you should create and throw the reason for that error in a custom exception. Then in main, you can tell the difference between your detected error and something you didn't expect. It's just good practice.
Well you "can" but it doesn't throw nothing. It terminates.
5.17 Throwing an exception:
Evaluating a throw-expression with an operand throws an exception (15.1)
A throw-expression with no operand rethrows the currently handled exception (15.3).
If no exception is presently being handled, evaluating a throw-expression with no operand calls std::terminate()
This is valid:
int main () {
throw;
return 0;
}
Source used: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
But it won't cleanup anything. std::terminate is used when the cleanups fail.
Otherwise you have to use operand, and then this section becomes relevant:
15.1 Throwing an exception [except.throw]
Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler (15.3).
So you have to pass something that is able to be initialized, which by definition cannot be nothing.
In order to ensure full cleanup you have to throw an exception and catch it somewhere. Implementations are not required to clean up stack objects when an exception is thrown but not caught. The requirement (in [except.handle]/9) when an exception is thrown but not caught is that the program calls std::terminate(), and it's implementation-defined whether stack objects are cleaned up.

Using RAII to nest exceptions

So the way to nest exceptions in C++ using std::nested_exception is:
void foo() {
try {
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
catch(...) {
std::throw_with_nested(std::runtime_error("foo failed"));
}
}
But this technique uses explicit try/catch blocks at every level where one wishes to nest exceptions, which is ugly to say the least.
RAII, which Jon Kalb expands as "responsibility acquisition is initialization", is a much cleaner way to deal with exceptions instead of using explicit try/catch blocks. With RAII, explicit try/catch blocks are largely only used to ultimately handle an exception, e.g. in order to display an error message to the user.
Looking at the above code, it seems to me that entering foo() can be viewed as entailing a responsibility to report any exceptions as std::runtime_error("foo failed") and nest the details inside a nested_exception. If we can use RAII to acquire this responsibility the code looks much cleaner:
void foo() {
Throw_with_nested on_error("foo failed");
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
Is there any way to use RAII syntax here to replace explicit try/catch blocks?
To do this we need a type that, when its destructor is called, checks to see if the destructor call is due to an exception, nests that exception if so, and throws the new, nested exception so that unwinding continues normally. That might look like:
struct Throw_with_nested {
const char *msg;
Throw_with_nested(const char *error_message) : msg(error_message) {}
~Throw_with_nested() {
if (std::uncaught_exception()) {
std::throw_with_nested(std::runtime_error(msg));
}
}
};
However std::throw_with_nested() requires a 'currently handled exception' to be active, which means it doesn't work except inside the context of a catch block. So we'd need something like:
~Throw_with_nested() {
if (std::uncaught_exception()) {
try {
rethrow_uncaught_exception();
}
catch(...) {
std::throw_with_nested(std::runtime_error(msg));
}
}
}
Unfortunately as far as I'm aware, there's nothing like rethrow_uncaught_excpetion() defined in C++.
In the absence of a method to catch (and consume) the uncaught exception in the destructor, there is no way to rethrow an exception, nested or not, in the context of the destructor without std::terminate being called (when the exception is thrown in the context of exception handling).
std::current_exception (combined with std::rethrow_exception) will only return a pointer to a currently handled exception. This precludes its use from this scenario as the exception in this case is explicitly unhandled.
Given the above, the only answer to give is from an aesthetic perspective. Function level try blocks make this look slightly less ugly. (adjust for your style preference):
void foo() try {
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
catch(...) {
std::throw_with_nested(std::runtime_error("foo failed"));
}
It's impossible with RAII
Considering the simple rule
Destructors must never throw.
it is impossible with RAII to implement the thing you want. The rule has one simple reason: If a destructor throws an exception during stack unwinding due to an exception in flight, then terminate() is called and your application will be dead.
An alternative
In C++11 you can work with lambdas which can make life a little easier. You can write
void foo()
{
giveErrorContextOnFailure( "foo failed", [&]
{
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
} );
}
if you implement the function giveErrorContextOnFailure in the following way:
template <typename F>
auto giveErrorContextOnFailure( const char * msg, F && f ) -> decltype(f())
{
try { return f(); }
catch { std::throw_with_nested(std::runtime_error(msg)); }
}
This has several advantages:
You encapsulate how the error is nested.
Changing the way errors are nested can be changed for the whole program, if this technique is followed strictly program wide.
The error message can be written before the code just as in RAII. This technique can be used for nested scopes as well.
There's less code repetition: You don't have to write try, catch, std::throw_with_nested and std::runtime_error. This makes your code more easily maintainable. If you want to change the behavior of your program you need to change your code in one place only.
The return type will be deduced automatically. So if your function foo() should return something, then you just add return before giveErrorContextOnFailure in your function foo().
In release mode there will typically be no performance panelty compared to the try-catch-way of doing things, since templates are inlined by default.
One more interesting rule to follow:
Do not use std::uncaught_exception().
There's a nice article about this topic by Herb Sutter which explains this rule perfectly. In short: If you have a function f() which is called from within a destructor during stack unwinding looking like this
void f()
{
RAII r;
bla();
}
where the destructor of RAII looks like
RAII::~RAII()
{
if ( std::uncaught_exception() )
{
// ...
}
else
{
// ...
}
}
then the first branch in the destructor will always be taken, since in the outer destructor during stack unwinding std::uncaught_exception() will always return true, even inside functions called from that destructor including the destructor of RAII.

Why bad_exception is not thrown automatically?

Why doesn't this piece of code run without error? Isn't bad_exception supposed to be called automatically when an unexpected exception is encountered? Or is it necessary to set a handler for it?
#include <iostream>
#include <exception>
using namespace std;
class C{};
void test() throw(bad_exception)
{
throw C();
}
int main()
{
try
{
test();
} catch(bad_exception& e)
{
cout << "Caught ";
}
}
In C++03 theory:
If you throw an exception that is not in the exception specification, unexpected() gets called. If you have not set the unexpected handler via set_unexpected() this means terminate() gets called which is the case you observed. If you have set an unexpected handler that does not call terminate but throws an exception, and if that exception is not listed in your exception specification, it gets translated into bad_exception. So in order to get the expected result, call set_unexpected() first with an appropriate handler.
In C++03 practice:
Some compilers do not support exception specifications at all (other than throw()), others just don't evaluate/check them for correctness. As Herb Sutter points out, exception specifications create a clumsy "shadow type system" that is not easy to handle right (if it is possible at all). Therefore..
... in C++11:
Exception specifications are deprecated. You should rather not use them. However, there is a nothrow operator that has a slightly different functionality than throw()
PS: so why have std::bad_exception in C++03?
You hav three different regions of code:
The function you are writing an exception specification for.
The "foreign" code you are calling from that function that might or might not throw an exception that does not match you specification.
The (maybe also unknown) unexpected handler that can be anything and should either terminate/exit/abort the program or throw anything.
So if the "foreign" code throws an exception that violates your exception specification, you have three possible outcomes of that:
The handler terminates the program. There is not much you can do about that unless you set your own handler in the function.
The handler throws an exception that matches your exception specification. And all is well.
The handler throws something else. What do you want the runtime to do now? That's where bad_exception comes in: If it is in your specification, the "something else" gets translated into a bad_exception, and the program continues. If it's not, terminate gets called.
Setting your own handler inside the function disables any handler that was previously set by anyone else who just wants to use your function. He will not expect you to disable his handler. Besides, the handler is meant as a global what-happens-if policy and thus is nothing you should care about in a single function implementation.
This should call std::unexpected which by default call std::terminate() as the thrown exception isn't part of the exception specification.
(It does here with g++ on Linux, SunOracle CC on Solaris, IBM xlC on AIX BTW)
If you install an unexpected handler, it works as you expect here:
include <iostream>
#include <exception>
using namespace std;
class C{};
void myunexpected()
{
throw std::bad_exception();
}
void test() throw(std::bad_exception)
{
throw C();
}
int main()
{
try
{
set_unexpected(myunexpected);
test();
} catch(std::bad_exception& e)
{
std::cout << "Caught ";
}
}
As per [except.unexpected], when a function throws an exception not listed in its dynamic exception specification, std::unexpected() is called. According to [unexpected.handler], the default implementation of std::unexpected() simply calls std::terminate().
However, the program can install its own handler, which can (re-)throw an exception. If the exception thus thrown is not allowed by the dynamic exception specification, it can be replaced by std::bad_exception when that is allowed.
Your catch-block would only catch exceptions of the type bad_exception, or a subtype thereof. C does not meet this criterion.
Actually, this question is very similar to yours. The accepted answer explains that if your function throws an exception that does not match the specification (if there is any), then std::unexpected is called, which by default calls std::terminate.

What is the point of `void func() throw(type)`?

I know this is a valid c++ program.
What is the point of the throw in the function declarement? AFAIK it does nothing and isnt used for anything.
#include <exception>
void func() throw(std::exception) { }
int main() { return 0; }
It specifies that any std::exception can be thrown from func(), and nothing else. If something else is thrown, it will call an unexpected() function which by default calls terminate().
What this means is that throwing something else will almost certainly terminate the program, in the same manner as an uncaught exception, but the implementation will have to enforce this. This is normally much the same as putting a try{...}catch(){...} block around func(), which can inhibit performance.
Usually, exception specifications aren't worth it, according to the Guru of the Week column about it. The Boost guidelines say that there might be a slight benefit with a blank throws() for a non-inline function, and there are disadvantages.
That is an exception specification, and it is almost certainly a bad idea.
It states that func may throw a std::exception, and any other exception that func emits will result in a call to unexpected().
This is a C++ exception specification. It declares that the particular function will potentially throw a std::exception type.
In general though exception specifications in C++ are considered a feature to avoid. It's an odd feature in that it's behavior is declared at compile time but only checked at runtime (very different from say Java's version).
Here is a good article which breaks down the feature
http://www.gotw.ca/publications/mill22.htm
This is an exception specification. It says that the only exception that func() can throw is std::exception (or a derivative thereof). Attempting to throw any other exception will give std::unexpected instead.
Exception specification. The type(s) following the throw keyword specifies exactly what all, if any, exceptions the function can throw. See 15.4 of the draft.
Note: A function with no exception-specification allows all exceptions. A function with an empty exception-specification, throw(), does not allow any exceptions.
Basically this:
void func() throw(std::exception,B) { /* Do Stuff */}
Is just shorthand fro this:
void func()
{
try
{
/* Do Stuff */
}
catch(std::exception const& e)
{
throw;
}
catch(B const& e)
{
throw;
}
catch(...)
{
unexpected(); // This calls terminate
// i.e. It never returns.
}
}
Calling terminate() is rarely what you want, as the stack is not unwound and thus all your efforts in RAII is wasted. The only exception to the rule is declaring an empty throw list and this is mainly for documentation purposes to show that you are supporting the no-throw exception gurantee (you should still manually catch all exceptions in this situation).
Some important (imho) places that should be no-throw are destructors and swap() methods. Destructors are rarely explicitly marked no-throw but swap() are quite often marked no-throw.
void myNoThrowFunc() throws() // No-Throw (Mainlly for doc purposes).
{
try
{
/* Do Stuff */
}
catch(...) // Make sure it does not throw.
{
/* Log and/or do cleanup */
}
}