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

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.

Related

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

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.

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.

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

Why does the code crash?

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.