Why is stack unwinding guaranteed only for handled exceptions? - c++

C++ standard says ([except.handle]/9):
If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined
For example, behavior of code below (will it print S::~S() or not) is implementation defined:
struct S {
S() { std::cout << "S::S()" << std::endl; }
~S() { std::cout << "S::~S()" << std::endl; }
};
int main() {
S s;
throw std::runtime_error("exception");
}
I would like to know in-depth: why is it implementation defined? Why a context cannot be unwinded up to its entry before std::terminate() is called if an exception is uncaught (which is similar to try{ ... } catch(...) { throw; } in the top-level function)? At a glance, such behavior is much clearer and safer in consistence with RAII.

If an exception isn't caught, std::terminate is called. We failed so bad the host environment needs to step in and (maybe) clean up after us. Unwinding the stack in this case is like giving a helmet to a kamikaze pilot.
So for a hosted environment, it may make more sense to just do nothing and let the host clean up.
Now, if you are in a stand alone implementation, and are throwing exceptions, then there is no one to clean up after you. An implementation should preform stack unwinding in this case, because that's what is supposed to clean up the mess.
The standard leaves it to the implementation to facilitate these two very different execution environments.
Like #Matteo pointed out, std::terminate is called before any potential unwinding because you can setup a handler for it. And that handler can do something useful with the stack state, so long as the stack isn't unwound yet.

Not the strongest reason per se, but leaving this up to the implementation allows for more optimizations. E.g.:
class Foo { /*...*/ };
void f();
int main()
{
for ( int i = 0; i < 1000000; ++i )
{
Foo myFoo;
f();
}
}
Here, an implementation may choose not to destroy myFoo if f() throws, which may reduce code size and/or increase performance. The rationale would be if you don't write an exception handler, you don't expect f() to throw anyway, and shortcuts may be taken. This may sound a bit weak, but this is similar to noexcept (C++11) vs. throw() clause (C++98) – removing the requirement to unwind the stack allows for more aggressive optimization.

Related

Can a noexcept function still call a function that throws in C++17?

In P0012R1, "Make exception specifications be part of the type system",
I see that noexcept is now becoming a part of the function type.
I can't tell whether this will prevent noexcept(true) functions from still being able to call noexcept(false) functions.
Will the following code still be valid for C++17?
void will_throw() noexcept(false){
throw 0;
}
void will_not_throw() noexcept(true){
will_throw();
}
According to cppreference:
Note that a noexcept specification on a function is not a compile-time
check; it is merely a method for a programmer to inform the compiler
whether or not a function should throw exceptions.
So the syntax of your code is valid, but std::terminate will be called when executed.
Unfortunately it is valid at compile time.
Although noexcept is used by the compiler to optimize the exception handling code, making the code more performant, it's a shame they didn't push it further to give noexcept a semantic meaning.
Ideally, when you mark a method as noexcept it should also mean that the method is not supposed to let any exceptions bubble up. So if you have a method marked as noexcept but it calls other methods that are not marked as noexcept, that should give you a compile error, unless there is a try/catch block surrounding anything that can throw.
Simply calling std::terminate is a very poor language design choice, because it doesn't put any responsibility at the hands of whoever writes the noexcept method. On the contrary, it harms software reuse by making it impossible even to the consumer to work the problem around.
For example, say that I am a bad library developer and I wrote the following code:
Header file Foo.h that ships with my library:
class Foo
{
public:
void DoSomething() noexcept;
};
You are happy consumer of FooLib writing a Bar application:
Bar.cpp
#include "Foo.h"
int main()
{
Foo foo;
try
{
foo.DoSomething();
}
catch (...)
{
std::cout << "Yay!" << std::endl;
}
return 0;
}
That code compiles fine and runs fine until you have Foo throwing an exception... And it doesn't make any difference if you enclose the call to foo.DoSomething() with a try/catch block. The code will simply abort.
If you don't have the code of Foo, you can't fix it. The only solution in this case is to throw away Foo library and write your own.
The contents of Foo.cpp can be something like this:
static void PotentiallyThrowException()
{
throw 0;
}
void Foo::DoSomething() noexcept
{
PotentiallyThrowException();
}
Note that it's up to the implementer of Foo::DoSomething() to wrap their own calls into try/catch. But due to the same issue, if they are calling other methods that are marked as noexcept and those developers didn't do the same, now it's Foo::DoSomething() that is hosed. And so on, and so forth.
We can safely say that from the semantic point of view noexcept is not only useless, but it's also harmful.
noexcept(true) functions can call noexcept(false) functions. There will be a runtime error if an exception is thrown. The canonical example of why this is allowed is:
double hypotenuse(double opposite, double adjacent) noexcept(true)
{
return std::sqrt(opposite*opposite + adjacent*adjacent);
}
std::sqrt will throw domain_error if its argument is negative, but clearly that will never happen here.
(In an ideal world, it would be forbidden by default with an exception_cast to allow it where required. The result could either be UB if an exception is thrown, or std::terminate).
Including the exception specification in the function type is orthogonal to whether a function can call another function with an incompatible exception specification (without handling the exceptions that were not included in its exception specification). The former is about type safety with respect to function pointers (so that you cannot call a throwing function through a function pointer that was known not to throw). Regarding the latter, we can either prohibit it during compilation (as in Java), or treat it as a runtime error (leading to the termination of the program, as is chosen for the C++ current standard).
One may argue by brining the analogy of calling a non-const (non-static) member function from a const (non-static) member function. However the difference is that indirectly modifying an object inside a non-const member function called through a const member function would go undetected (or else would be too costly to detect) and may lead to nasty bugs, that's why it has to be prevented during compilation. Whereas the act of throwing an exception is (should be) an exceptional event and we can afford inserting run-time checks of whether the exception complies with the exception specification and should be let out, or it violates the program logic and should instead terminate the program.

Does noexcept apply to exceptions propagating from initializer lists

Lets say I have a constructor like so
Something(SomethingElse) noexcept : member{SomethingElse, something_that_might_throw()} {
...
}
Is a noexcept okay in this case if the construction of member can throw? In the above example the member variable member is of a type I do not know.
On a side note: Are there other edge cases one needs to worry about when using noexcept?
#UPDATE:(Based on your edit): The original answer applies to everything within the block-scope of the function (constructors inclusive, including constructor-initialization-list). Why don't you try the code and see. :-)
#Original Answer
Something(SomethingElse) : member{SomethingElse} noexcept {
...
}
Your code would not compile that way. noexcept comes before the colon :
Something(SomethingElse) noexcept : member{SomethingElse} {
...
}
To your question:
Is a noexcept okay in this case if the member class constructor can
throw?
No, it's not okay. The noexcept specifier is a promise that an exception will not leave that function or constructor. Should it leave, the runtime will terminate your program.
If a search for a matching exception handler leaves a function marked
noexcept or noexcept(true), std::terminate is called immediately.
This applies to the constructor.
Despite the try..catch block, the code below gets terminated:
struct Base {
Base(){}
Base(int){ throw int(5); }
};
struct Derived : public Base {
Derived(int a) noexcept : Base(a) {}
};
int main()
{
try{
Derived d(45);
} catch(...) {}
return 0;
}
Output:
terminate called after throwing an instance of 'int'
bash: line 7: 7454 Aborted (core dumped) ./a.out
See it Live on Coliru
But if you remove the noexcept specification, you wouldn't abruptly end your program, exception handling will continue normally. :-).
I'll leave you to think of the consequences if you do this kind of thing in production or even a large code base with many contributors. Do not use noexcept if you are unsure of the exception guarantees of all the statements in your function/constructor block
Yes, a noexcept on a constructor applies to base class/member construction.
If you need to deal with such a case, you probably want to use the little-known (and rarely used) function try block. The syntax looks something like this:
#include <iostream>
class bad_initializer {};
int do_throw() {
throw bad_initializer();
return 1;
}
class something {
int member;
public:
something() noexcept
try : member{do_throw()} // <-- initializer list
{
// ctor body goes here
}
catch(bad_initializer const &) {
std::cerr << "initialization threw\n";
}
};
int main() {
something s;
}
Now, the bad news: since you have a member that wasn't constructed, the catch block really has only a few options. Normal processing can't continue--an exception happened in constructing the object, which means the object can't ever finish construction. By the time you catch the exception, there's nothing you can do about that.
If it weren't noexcept, it could catch the exception, then do some processing (release any resources it did acquire successfully) then either rethrow the exception it caught, or throw a different exception (one that better reflected its inability to be constructed).
In this case, your meaningful choices are even more restricted: you can call terminate directly, or you can throw an exception, which will call terminate indirectly. About all the whole try/catch thing has done in this case is give you a chance to do a little processing before terminate gets called.
In general it's not okay, but in certain circumstances it may be
noexcept is a promise, similar to the const qualifier of member functions, but unlike const it's not enforced at compile time (the compiler will not issue an error and perhaps not even a warning, if a noexcept function may actually throw, but see below). Thus, you can declare a function noexcept even if a compiler-generated check would find that this function may throw and the code will compile (otherwise your question would be impossible).
However, that defeats the purpose of noexcept. The main purpose is to indicate (1) to the programmer that they can use a certain functionality without worrying about exception safety, and (2) to the compiler that it does not need to add code for stack unwinding. Instead, if an exception is thrown in a noexcept function, the run-time will invoke std::terminate(), as required by the standard.
So, in general your constructor should only be noexcept, if all its functionality, including the construction of bases and members is too.
However, there is an exception. If you know that some method will never throw given any input possible in the particular situation, even if it may throw under other circumstances and hence not be noexcept, you can call this method in a noexcept situation. For example,
// requires non-negative x, will throw std::runtime_error for negative x
int my_func(std::int64_t x);
struct my_struct {
std::int64_t q;
my_struct(int x) noexcept : q(std::int64_t(x)*std::int64_t(x)) {}
int member() const noexcept { return my_func(q); } // fine: q>=0
};
In the situation of your post, this means if member(somethingelse_type) is not noexcept, but you know (from conditions outside the code snipped in your post) that no exception will be thrown for the particular argument provided in this circumstance, you may declare Something(SomethingElse) noexcept.

Constructors and Exceptions

I was reading some notes on C++ and came across the following question
Q: Can a constructor throws an exception? How to handle the error when the constructor fails?
A:The constructor never throws an error.
Now this answer kind of confused me and just to make sure I went online and read that you could always throw exceptions from a constructor. I just wanted to make sure if this way a typo in the notes and that I may not be missing something important.
The notes are wrong, if they're talking about constructors in general. Ctors can indeed throw normally. Perhaps that was discussing a particular class which guarantees nonthrow construction?
On the other hand, it's strongly encouraged to code so that your destructors never throw. It's legal for them to do so, but throwing an exception during stack unwinding results in immediate program termination (a call to std::terminate).
Of course, it can. Even standard containers (e.g. std::vector) throw std::bad_alloc from constructors. This FAQ is telling the truth.
You can throw an exception from a constructor, but be careful: if object is not properly constructed, destructor will not be called.
class Foo
{
public:
Foo(int i)
{
throw i;
}
~Foo()
{
std::cout << "~Foo()" << std::endl;
}
};
int main()
{
try
{
Foo f(42);
}
catch(...)
{
std::cout << "Catched" << std::endl;
}
return 0;
}
Output:
Catched
To fix this you should encapsulate one constructor into another:
Foo()
{
}
Foo(int i): Foo()
{
throw i;
}
Output:
~Foo()
Catched

confusion about non-throw functions

I have 2 questions about non-throwing functions:
Why make a function non-throwing?
How to make a function non-throwing? If the code inside the function actually may throw, then should I still make it non-throwing?
Here is an example:
void swap(Type t1, Type t2) throw()
{
//swap
}
If the code in swap won't throw at all, should I still append throw()? Why?
throw() (or noexcept in C++11) is useful for two reasons:
It allows the compiler to be more aggressive in its optimisations.
It tells function users that they can use this function in their own non-throwing functions.
Non-throwing functions are very important for writing exception safe code. For instance, the usual way of writing an exception safe operator= is via a non-throwing swap() function.
On the other hand, other exception specifications are useless and have been justly deprecated in the current standard. They don't mix well at all with templates and are too expensive to enforce.
Now, if you use a noexcept specification in a function that might actually throw, all bets are off. Even if your compiler does not terminate the program when an exception leaves the function (VS does not do it for runtime efficiency reasons, for instance), your code might not do what you thought because of optimisations. For example:
void f() noexcept
{
a();
b();
}
If a() actually throws and b() has side effects, the function behaviour will be unpredictable, because your compiler may decide to execute b() before a(), since you have told it that no exceptions will be thrown.
EDIT: Now for the second part of your question: how to make a function non-throwing?
First you need to ask yourself whether your function should really be non-throwing. For instance:
class C
{
C* CreateInstance()
{
return new C();
}
}
Since operator new can throw a std::bad_alloc, CreateInstance() can throw. You could try to avoid it with a try-catch block, handling or swallowing any exceptions that may be thrown inside the try block, but would that really be sensible? For instance:
C* CreateInstance()
{
try
{
return new C();
}
catch (...)
{
return null;
}
}
Problem solved, it seems, but would your callers be prepared for CreateInstance() returning null? If not, a crash will ensue when they try to use that pointer. Besides, a std::bad_alloc usually means that you have run out of memory and you would just be postponing the problem.
So be careful: some functions can be made non-throwing, but others should be allowed to throw. Exception safety is not a trivial matter.
Why make a function non-throwing?
So callers of the function can call it without having to take any actions to deal with exceptions being raised by the function.
How to make a function non-throwing? If the code inside the function actually may throw, then should I still make it non-throwing?
You can make the code non-throwing by putting all code which could throw the inside a try block, and deal with any exceptions without re-throwing.
void swap(T t1, T t2) noexcept {
try {
// ....
} catch (const std::exception& ex) {
// ....
} catch (...) {
// ....
}
}
If you claim your function doesn't throw, then you have to make it non-throwing. But this doesn't mean adding an exception specification, which you shouldn't do anyway, since it is deprecated. It means you must ensure the function doesn't throw, no matter what. The C++11 keyword noexcept gives you some compile-time safety in this respect.

Destructor not invoked when an exception is thrown in the constructor

Why is the destructor not invoked in this code?
#include <boost/scoped_ptr.hpp>
#include <iostream>
class MyClass {
boost::scoped_ptr<int> ptr;
public:
MyClass() : ptr(new int) { *ptr = 0; throw; std::cout<<"MyClass Allocated\n"; }
~MyClass() { std::cout<<"MyClass De-allocated\n"; }
int increment() { return ++*ptr; }
};
int main()
{
boost::scoped_ptr<MyClass> myinst(new MyClass);
std::cout << myinst->increment() << '\n';
std::cout << myinst->increment() << '\n';
}
EDIT
From the answers, In understand that when an exception happens in the constructor, destructor will not be invoked. But if the exception happens in the main(), ie after the MyClass object is fully instantiated, will the MyClass destructor be invoked? If not, then why it is a smart pointer?
Adding the code
#include <boost/scoped_ptr.hpp>
#include <iostream>
class MyClass {
boost::scoped_ptr<int> ptr;
public:
MyClass() : ptr(new int) { *ptr = 0; std::cout<<"MyClass Allocated\n"; }
~MyClass() { std::cout<<"MyClass De-allocated\n"; }
int increment() { return ++*ptr; }
};
int main()
{
boost::scoped_ptr<MyClass> myinst(new MyClass);
throw 3;
std::cout << myinst->increment() << '\n';
std::cout << myinst->increment() << '\n';
}
Output:
MyClass Allocated
terminate called after throwing an instance of 'int'
Aborted
A C++ object's lifetime begins only after its constructor completes successfully.
Since the exception was thrown before constructor call was complete you don't have an complete object and hence no destructor.
Herb Sutter explains this nicely, to quote him:
Q: What does emitting an exception from a constructor mean?
A: It means that construction has failed, the object never existed, its lifetime never began. Indeed, the only way to report the failure of construction -- that is, the inability to correctly build a functioning object of the given type -- is to throw an exception. (Yes, there is a now-obsolete programming convention that said, "if you get into trouble just set a status flag to 'bad' and let the caller check it via an IsOK() function." I'll comment on that presently.)
In biological terms,
conception took place -- the constructor began -- but despite best efforts it was followed by a miscarriage -- the constructor never ran to term(ination).
Incidentally, this is why a destructor will never be called if the constructor didn't succeed -- there's nothing to destroy. "It cannot die, for it never lived." Note that this makes the phrase "an object whose constructor threw an exception" really an oxymoron. Such a thing is even less than an ex-object... it never lived, never was, never breathed its first. It is a non-object.
We might summarize the C++ constructor model as follows:
Either:
(a) The constructor returns normally by reaching its end or a return statement, and the object exists.
Or:
(b) The constructor exits by emitting an exception, and the object not only does not now exist, but never existed as an object.
EDIT 1:
But if the exception happens in the main(), ie after the MyClass object is fully instantiated, will the MyClass destructor be invoked?
Yes, it will be!
That is the purpose of using scoped_ptr, Once an exception is thrown in main, Stack Unwinding would cause all local objects to be deallocated, this means that myinst(which resides on stack) will also be deallocated, which in turn will call the destructor of MyClass.
Refer the Boost doccumentation when in doubt:
The scoped_ptr class template stores a pointer to a dynamically allocated object. (Dynamically allocated objects are allocated with the C++ new expression.) The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, or via an explicit reset
EDIT 2:
Why does your edited program crash?
Your program shows crashes because, You throw an exception but you never catch it. when such a scenario occurs an special function called terminate() is called whose default behavior is to call abort().It is implementation defined behavior whether stack is Unwound before terminate() is called in this particular scenarioRef 1.Seems your implementation doesn't & you should not rely on this behavior as well.
You can modify your program as follows to handle the exception and you should get the behavior you were expecting:
#include <boost/scoped_ptr.hpp>
#include <iostream>
class MyClass {
boost::scoped_ptr<int> ptr;
public:
MyClass() : ptr(new int) { *ptr = 0; std::cout<<"MyClass Allocated\n"; }
~MyClass() { std::cout<<"MyClass De-allocated\n"; }
int increment() { return ++*ptr; }
};
void doSomething()
{
boost::scoped_ptr<MyClass> myinst(new MyClass);
throw 3;
}
int main()
{
try
{
doSomething();
}
catch(int &obj)
{
std::cout<<"Exception Handled";
}
}
Ref1C++03 15.5.1 The terminate() function
In the following situations exception handling must be abandoned for less subtle error handling techniques:
....
— when the exception handling mechanism cannot find a handler for a thrown exception (15.3),
....
In such cases,
void terminate();
is called (18.6.3). In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before terminate() is called. In all other situations, the stack shall not be unwound before terminate() is called. An implementation is not permitted to finish stack unwinding prematurely based on a determination that the unwind process will eventually cause a call to terminate().
Because calling the destructor doesn't make sense in this case.
You only destruct things which are constructed, yet your object never fully constructs. Your class members have been constructed, though, and will have their destructors called.
If a constructor throws exception, then the destructor of the class will not be called, because the object is not fully constructed.
See this link how to manage resources in such situation:
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10
When the exception is thrown from the constructor (beginning or half way or at the end of the call), then it's assured that the object is not constructed.
So it's well defined not to invoke the destructor of an object which was never constructed.
Here is one related FAQ from Bjarne's website.
The destructor for MyClass was never invoked because no objects of type MyClass were ever constructed. Each attempt to construct one was aborted, due to the exception being thrown.
As an aside, if you want your debug messages to display -- especially if you're dealing with the program crashing -- you really ought to flush the streams: i.e. using std::endl instead of '\n' at the end of line. (or inserting std::flush)
While merely using '\n' often works, there are enough situations where it fails and it's really, really confusing to debug if you don't make a habit of doing things right.