Why does the code crash? - c++

Looking on the internet for C++ brainteasers, I found this example:
#include <iostream>
using namespace std;
class A {
public:
A()
{
cout << "A::A()" << endl;
}
~A()
{
cout << "A::~A()" << endl;
throw "A::exception";
}
};
class B {
public:
B()
{
cout << "B::B()" << endl;
throw "B::exception"; // <- crashes here
}
~B()
{
cout << "B::~B()";
}
};
int main(int, char**) {
try
{
cout << "Entering try...catch block" << endl;
A objectA;
B objectB;
cout << "Exiting try...catch block" << endl;
}
catch (const char* ex)
{
cout << ex << endl;
}
return 0;
}
This is what I thought the program would do:
A::A() will be output to screen when the constructor of objectA is called. Object A is constructed successfully.
B::B() will be output to screen when the constructor of objectB is called.
The constructor of B then throws an exception. Object B is not constructed successfully.
Destructor of objectB is not called as the constructor never completed successfully.
Destructor of objectA will be called as the object goes out of scope when the try block is exited.
However, when I ran the program, it actually crashed at the line marked with <-. Could anybody explain what exactly was going on at that point?

If you are really coding, not just brainteasing never ever throw exception from destructor. If an exception is thrown during stack-unwinding, terminate() is called. In your case destructor of A has thrown while processing exception that was thrown in B's constructor.
EDIT:
To be more precise (as suggested in comments) - never ever let exception escape destructor. Exceptions that are caught inside destructor make no problem. But if during stack unwinding program has to deal with two exceptions - the one that caused stack unwinding and the one that escaped destructor during unwinding, std::terminate() goes.

When B::B() throws an exception stack unwinding begins. A::~A() is called and throws another exception that is not catched inside A::~A().
If another exception leaves a destructor while stack unwinding is in progress terminate() is called and that looks like a program crash.

Golden rule in C++ - destructors should never throw exceptions. Ignoring this rule will lead to undefined behaviour in all sorts of situations.

The code crashes because B's C'tor throws an exception, and then starts the "Stack Unwinding" procedure: all the local objects are destructed, dus, A's D'tor is called, and throws an exception during the Stack unwinding, and then "abort" is called, because there can't be two exceptions at the same time...
Conclusion:
Never throw an exception from a D'tor, because you might be throwing it during Stack Unwinding.

A::~A() is called when the try block is exited, precisely because the object goes out of scope. This is why RAII works --- it depends on destructors being called regardless of why the scope is exited.
A::~A() then throws an exception. As B::B()'s exception is still being thrown up the stack, this crashes the program.

Your should NEVER throw an exception in destructor. Take a look at this question why.

Related

What does "Lifetime of Object" actually mean? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can a local variable’s memory be accessed outside its scope?
Code:
#include <iostream>
using namespace std;
class B{
public:
int b;
B():b(1){}
~B(){cout << "Destructor ~B() " << endl;}
};
class A{
public:
B ob;
A()try{throw 4;}
catch(...){cout << "Catched in A() handler : ob.b= " << ob.b<<endl;}
};
int main()try{
A t;
}
catch(...){cout << "CATCHED in Main" << endl;}
Output:
Destructor ~B()
Catched in A() handler : ob.b= 1
CATCHED in Main
My Question is how it's possible to access a member variable b of an object ob that its destructor call finished.
Using a destructed object is undefined behaviour. This means that you may be getting this behaviour now, but nothing guarantees that you will get it some other time. Undefined behaviour is more dangerous than a regular bug because it can be more difficult to detect, as this example shows.
UPDATE: Following some comments, I'll explain why OP's code produces that output.
try function blocks are a somewhat obscure feature in C++. You can surround the whole body of a function inside a try block, with its corresponding catch. This is, instead of:
void foo()
{
try
{
//...
}
catch (/*whatever*/)
{
//...
}
}
You can write:
void foo()
try
{
//...
}
catch (/*whatever*/)
{
//...
}
This is not too useful, really, but can be marginally useful for constructors, because this is the only way to include the initialisation list inside the try block. Thus, OP's code for the A constructor is equivalent to:
A()
try
: b()
{
throw 4;
}
catch(...)
{
cout << "Catched in A() handler : ob.b= " << ob.b<<endl;
}
I said this is just marginally useful because you cannot use the object you are constructing inside the catch block; if you throw inside the try block, the exception will leave the constructor body, so the object will have never been constructed and any constructed data member will be immediately destructed before entering the catch block. But it might have some use for logging purposes.
Now, as we all know, a constructor (asuming we are not using the nothrow version) can only do two things:
Return a constructed object
Throw an exception
In this constructor we throw, but the exception is caught in the catch block. So what happens now? What will be returned to the code calling the constructor? We cannot return a constructed object because we have none, so there is only one alternative: the catch block must throw. And this is actually what the standard mandates in this case. If we do not throw explicitly, the compiler will silently add a throw; instruction at the end of the catch block. So, elaborating a bit more, the constructor is equivalent to the following:
A()
try
: b()
{
throw 4;
}
catch(...)
{
cout << "Catched in A() handler : ob.b= " << ob.b<<endl;
throw;
}
And this is the reason why the exception is caught twice: once in A constructor and once in main().
Because while the object has been destroyed, the actual memory that it occupied still exists. However, it's undefined behavior, and may or may not work.
That might be a bug in your compiler.
When I ran your code, the destructor is called in the proper order. The output is:
Catched in A() handler : ob.b= 1
Destructor ~B()
And I can't imagine any reason why catch in main is executed. The exception was already caught in A::A().
Update
I was confused by the edit. Originally, it was initializer list try/catch syntax which makes a difference. Now I can reproduce OP's output and it is UB indeed. I got a crash.

Throwing an exception in a destructor and subsequent destructors

I did an experiment with throwing an exception from a destructor and got a result that I did not expect. See the code snippet:
#include <iostream>
#include <exception>
class A
{
public:
~A() noexcept(false)
{
std::cout << "in ~A" << std::endl;
//throw std::runtime_error("~A exception");
}
};
class M
{
public:
~M() noexcept(false)
{
std::cout << "in ~M" << std::endl;
//throw std::runtime_error("~M exception");
}
};
class B : public A
{
public:
~B() noexcept(false)
{
std::cout << "in ~B" << std::endl;
throw std::runtime_error("~B exception");
}
private:
M m;
};
class X
{
public:
~X() noexcept(false)
{
std::cout << "in ~X" << std::endl;
//throw std::runtime_error("~X exception");
}
};
int main()
{
try
{
X x;
B b;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
return 0;
}
the output:
in ~B
in ~M
in ~A
in ~X
~B exception
0
so the question is: is this correct that if I throw an exception from a destructor it is caught then all the subsequent destructors (including the destructors of the base class, class members and the destructors of the objects declared on the stack (as X, for example)) are called and then the exception is rethrown?
EDIT1:
The same result if I modify main() as follows:
int main()
{
try
{
X x;
B * b = new B();
delete b;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
return 0;
}
and then the exception is rethrown?
No, it is not "rethrown". The destructors are being called as part of throwing (and catching) the exception. This is slightly a semantical difference, but an exception gets thrown only once, here, and the objects get destroyed as part of the exception getting thrown.
Let's set aside the issue of throwing exceptions from destructors (which is, in itself, an iffy topic). Consider the following code:
void function()
{
X some_object;
throw std::runtime_error("bad");
}
X's destructor gets called here as part of throwing the exception. Why? Because the object is getting destroyed. The destructor gets called no differently from what it gets called if this function returns normally. The only difference is that instead of returning to the caller, the execution returns to wherever the exception gets caught (presuming that it gets caught). But, either way, execution leaves this scope, which means that the automatically-scoped object must get destroyed, which means that its destructor must get called.
A destructor of an automatically-scoped object gets called whenever execution leaves the object's automatic scope. Whether the scope is left voluntarily, or involuntarily due to a thrown exception, makes no difference.
In your case, this is no different. In fact, your code already entered the most derived-object's destructor as part of destroying it normally (via delete or by leaving the automatic object's scope). The fact that an exception gets thrown does not really change, much, the fact that the objects get destroyed. The only difference is that the object get destroyed as part of throwing an exception, since the execution moves where it gets caught, but whether the execution moves to where it gets returned or, or where its exception gets caught, makes no difference with regards to the destructor invocation.

An exception gets thrown twice from a constructor with a function-try-block

Why does the following exception thrown from the constructor of class A get caught twice, first by the catch within the constructor itself and second time by the catch in the main function?
Why doesn't it get caught just once by the catch within the constructor?
#include <iostream>
using namespace std;
class E {
public:
const char* error;
E(const char* arg) : error(arg) { }
};
class A {
public:
int i;
A() try : i(0) {
throw E("Exception thrown in A()");
}
catch (E& e) {
cout << e.error << endl;
}
};
int main() {
try {
A x;
}
catch(...)
{
cout << "Exception caught" << endl;
}
}
If I remove the try-catch block in the main function, the program will crash.
Here is the output:
Exception thrown in A()
terminate called after throwing an instance of 'E'
zsh: abort (core dumped) ./main
Why does it crash without the try-catch block in the main function?
Function-try-blocks in a constructor cannot prevent exceptions. Once an exception occurs in a constructor, you have no object, and the exception must propagate. The only thing the function-try-block can do is some local clean-up.
Constructors are indeed a very special animal with regards to function-try-blocks.
Cf. C++11 15.3/14:
The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.
Tl;dr: Do not use function-try-blocks, ever.
It seems logical. Consider two following scenarios.
i. Try block is inside constructor's body:
A() : i(0) {
try
{
throw E("Exception thrown in A()");
}
catch (E& e) {
cout << e.error << endl;
}
// If code reaches here,
// it means the construction finished well
}
ii. Try block is in initializer ctor:
A() try : i(0) {
throw E("Exception thrown in A()");
}
catch (E& e) {
cout << e.error << endl;
// OK, you handled the exception,
// but wait you didn't construct the object!
}
In the first case, after an exception, you will handle it inside the constructor and then you will construct the object properly.
In the second case, after an exception you will handle it there. BUT you didn't construct the object yet and you have no object in the caller's side. The caller should handle an un-constructed object situation.
You are utilizing a feature called function-try-catch. When used in a constructor, it allows catching exceptions in the initialization list (especially useful for catching exceptions in base class constructors) as well as the constructor body. But since the exception is thrown in a constructor, the class is incomplete, so the compiler automatically rethrows any caught exception.
that is why you see it caught twice.
Read the following article for more details:
Constructors and Exception in C++

Order of subobject destruction when an exception is thrown from the constructor

This question is inspired by Using an object after it's destructor is called
Let's consider the following code
class B
{
public:
B() { cout << "Constructor B() " << endl; }
~B() { cout << "Destructor ~B() " << endl; }
};
class A {
public:
B ob;
A()
try
{
throw 4;
}
catch(...)
{
cout << "Catch in A()\n";
}
A(int)
{
try
{
throw 4;
}
catch(...)
{
cout << "Catch in A(int)\n";
}
}
};
int main()
{
try
{
A f;
}
catch (...)
{
cout << "Catch in main()\n\n";
}
A g(1);
}
It's output is
Constructor B()
Destructor ~B()
Catch in A()
Catch in main()
Constructor B()
Catch in A(int)
Destructor ~B()
In contrast to A(int), constructor A() has the initializer list try/catch syntax. Why that makes a difference on the order of the subobject destruction? Why the exception thrown in A() propagates to main()?
Why that makes a difference on the order of the subobject destruction?
When catch in A(int) - all subobjects are alive, and you can use them. Moreover, after catch, you can continue object construction, and "return" to user properly constructed object.
When catch in A() - all subobjects, which were constructed - are destructed. And you don't know which subobjects were constructed and which not - at least with current ISO C++ syntax.
Why the exception thrown in A() propagates to main()?
Check GotW #66:
If the handler body contained the statement "throw;" then the catch block would obviously rethrow whatever exception A::A() or B::B() had emitted. What's less obvious, but clearly stated in the standard, is that if the catch block does not throw (either rethrow the original exception, or throw something new), and control reaches the end of the catch block of a constructor or destructor, then the original exception is automatically rethrown.
Think about what this means: A constructor or destructor function-try-block's handler code MUST finish by emitting some exception. There's no other way. The language doesn't care what exception it is that gets emitted -- it can be the original one, or some other translated exception -- but an exception there must be! It is impossible to keep any exceptions thrown by base or member subobject constructors from causing some exception to leak beyond their containing constructors.
In fewer words, it means that:
If construction of any base or member subobject fails, the whole object's construction must fail.
The difference is that at the end of:
A()
try
{
throw 4;
}
catch(...)
{
cout << "Catch in A()\n";
}
the exception is implicitly rethrown and no object A get constructed, whereas in:
A(int) {
try
{
throw 4;
}
catch(...)
{
cout << "Catch in A(int)\n";
}
}
you swallow the exception and an instance of A is fully constructed.
Destructors run only on fully constructed objects, that is objects whose constructor finished successfully, without throwing an exception.
EDIT: as per the destruction of subobjcets, the catch in the first case is run after the sub-object has been destructed. This is consistent with the member initialization syntax that suggests that it is what should actually happen:
A()
try : ob() // default construct
{
throw 4;
}
catch(...)
{
// here ob is already destructed
cout << "Catch in A()\n";
}
(equivalent to the first case.)
Why that makes a difference on the order of the subobject destruction?
In general, in the function catch clause of A(), you wouldn't know which members had been successfully constructed, because the exception might have come from one of their constructors. So to remove doubt they're destroyed first. Basically the function try/catch is "outside" the data member construction.
Why the exception thrown in A() propagates to main()?
The function catch clause can't make the constructor succeed (because if its members weren't constructed successfully, then the object itself hasn't been constructed successfully). So if you don't throw something else from it then the original exception is rethrown. That's just how it's defined, you can't use a function-try clause to ignore the problem. You can use a regular try/catch inside a function to ignore a problem, then it's up to you to decide whether or not the problem has prevented the object from being correctly constructed.

Some Question regarding Exception handling

Please have a look at demo code :
class myError
{
const char* str;
public:
myError():str(NULL) {}
myError(const char* temp)
{
str = temp;
}
const char* what()
{
return str;
}
};
class ab
{
int x;
public:
ab() try :x(0)
{
throw myError("error occured in the constructor of class ab");
}
catch(myError& temp)
{
std::cout<<"Handler no. 1 of ab constructor"<<std::endl;
}
};
int main () try
{
ab bb;
cout << "Resumed execution!" << endl;
return 0;
}
catch(myError& temp)
{
std::cout<<"Handler below the main function"<<std::endl;
std::cout<<"And the error is :" <<temp.what();
}
My Questions :
Why only function try block's handler of ctor and dtor only rethows the exception? ,
and when you simply throw exception inside ctor , its handler doesn't rethrows the object? i.e
Ctor::Ctor()
{
try{
throw Excep1();
}
catch(Excep1& temp) {
std::cout<<"Doesn't rethrows the exception object";
}
}
I wanna know that how to resume the control back to cout << "Resumed execution!" << endl; , after handling rethrown object?
why is it often said that we shouldn't place function try block on dtor of base class?
The usual rule is that a catch block doesn't rethrow unless you ask it
to. How would you stop the exception from propagating otherwise. In
the case of a constructor, however, if something in the initialization
list throws, then you haven't got a fully constructed object; there is
nothing you could do with the object, not even call the destructor on
it. And if the function catch block of the constructor doesn't
rethrow, what is it going to do, since it cannot simply return (and
leave the variable on the stack)?
In all other cases, it's up do the function containing the catch block
to know what to do. In the case of your main, for example, you could
write:
try {
ab bb;
} catch (...) {
}
std::cout << "Resumed execution!" << std::endl;
What you can't do is execute code where bb would be in scope and
accessible, but not have been correctly constructed.
As for why you shouldn't place a function try block on the destructor of a
base class, I've never heard that rule. In general, destructors
shouldn't throw, so there's no point in wrapping them in a try block,
period.
For the second question, destructors shouldn't be throwing period. Consider a case where your destructor is freeing a lot of memory through delete. What would happen if your destructor threw an error before finishing the clean up? You now have a memory leak. If your destructor is causing a runtime error, then you probably have problems elsewhere in your code that you need to fix.
As usually, Herb Sutter knows and explains everything:
If the handler body contained the statement "throw;" then the catch block would obviously rethrow whatever exception A::A() or B::B() had emitted. What's less obvious, but clearly stated in the standard, is that if the catch block does not throw (either rethrow the original exception, or throw something new), and control reaches the end of the catch block of a constructor or destructor, then the original exception is automatically rethrown.
More in his article