This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What happens to base class destructor if a derived class destructor throws an exception
If I throw an exception in the constructor of a derived class, is the destructor called to clean up the base class?
The destructors of the base class(es) are then called in the reverse order.
Before that, the destructors of any already initialized member will also get called.
However, the destructor of the currently constructed derived-class won't get called, as this part of the object will not have been really constructed yet.
Yes. For example, consider:
#include <iostream>
class B
{
public:
B() { std::cout << "B()\n"; }
~B() { std::cout << "~B()\n"; }
};
class D : public B
{
public:
D() { std::cout << "D()\n"; throw 23; }
~D() { std::cout << "~D()\n"; }
};
int main()
try
{
D d;
return 0;
}
catch(...) {}
Output:
B()
D()
~B()
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10
Every data member inside your object should clean up its own mess.
If a constructor throws an exception, the object's destructor is not
run. If your object has already done something that needs to be
undone (such as allocating some memory, opening a file, or locking
a semaphore), this "stuff that needs to be undone" must be
remembered by a data member inside the object.
Base destructors are guaranteed to be called, but not the destructor of the object itself.
Yes. Once construction of a base or member sub-object is complete, that sub-object will be properly destroyed if an exception is thrown.
Actually, throwing an exception in the constructor is one of the COMMON ways to detect object construction failure as long as it's properly handled by the caller, as there is NO return value of constructor.
Related
I've found what looks like contradictory answers regarding exceptions being thrown inside constructors in C++. One of the answers in this link says that if an exception is thrown inside a constructor, it is assumed that construction is not complete, and therefore the the destructor is not called. But this link discusses the RAII concept, using the example of a mutex created in a constructor and cleaned up in a destructor. It says that if a mutex is created in the constructor and then the constructor calls a function that throws an excpetion and no exception handler is defined, then the destructor will still be called and the mutex will be cleaned up. What
am I missing?
The destructor of the object being constructed is not executed, but all its members that were constructed are destructed; for example:
struct A {
A(int x) { ... }
~A() { ... }
};
struct B {
A a1, a2, a3;
B() : a1(1), a2(2), a3(3) { ... }
~B() { ... }
};
if when building a B instance the construction of a1 goes well, then the construction of a2 goes well but the construction of a3 throws an exception then what happens is that a2 will be destroyed (calling ~A), then a1 will be destroyed but ~B will NOT be called because the constructor didn't complete (the body didn't even start).
Even if the exception is thrown inside the ... body of B() then all of the A subobjects will be destroyed by calling ~A but still ~B will not be called.
Only if the constructor of B is completed what you get is a real B instance and then, when destroyed, ~B will be called to execute destruction code.
Let's look at this piece of code:
#include <iostream>
#include <stdexcept>
class A {
public:
A() {
std::cout << "A's constructor\n";
}
~A() {
std::cout << "A's destructor\n";
}
};
class B {
public:
B() {
std::cout << "B's constructor - begin\n";
throw std::runtime_error("Error");
std::cout << "B's constructor - end\n";
}
~B() {
std::cout << "B's destructor\n";
}
private:
A a;
};
int main() {
try {
B b;
} catch(const std::runtime_error& exc) {
std::cerr << exc.what() << '\n';
}
}
Here's the program's output:
A's constructor
B's constructor - begin
A's destructor
Error
In general, when an object is constructed first its fileds's constructors are invoked and then the constructor for the object is executed. For every successfully executed constructor there must be a destructor called. The destructors are called in reverse order. If a constructor fails then there's no destructor called but if during construction of an object some or all of its fields are constructed then they will be destroyed.
Coming back to the example, in the main function I create an object of class B. The object contains a member of class A. When the b object is created, first it's fields (in this case it's the member called a) are constructed - this is the first line of the output. Then the constructor of the b object begins execution (second line of output). The B's constructor throws an exception. Since the contructor of b's field (that is constructor of a) has already been successfully executed, a's destructor must be called - thrid line of output. Now, the b's constructor has not successfully finished its execution so the destructor is not going to be called for b. The last line of output is the effect of exception handling code in the main function.
In this example you can see that when a constructor succeeds then some time later a corresponding destructor is called. However if a constructor fails no destructor for the object will be called.
Successfully executed constructors and destructors are always paired. It's a very general rule and it's valid also for base classes (if any), objects allocated in arrays, objects allocated on stack etc. - even very weird and complicated cases are always handled this way.
Can anyone explain me why the output of the below snippet is :
MyClass constructor
catch block
Why is the destructor of object m not been called as the scope of it is within try block?
When it comes to catch block with throw 0; statement, the object m of MyClass is out of scope and its destructor should have been invoked right?
Am i missing some kind of concept hear?
class MyClass {
public:
MyClass() {
std::cout << "\nMyClass constructor" ;
throw 0;
}
~MyClass() {
std::cout << "\nMyClass destructor" << std::endl;
}
};
int main(void)
{
try {
MyClass m;
} catch(int e) {
std::cout << "\ncatch block" << std::endl;
}
return 0;
}
According to
[dcl.init]/21
An object whose initialization has completed is deemed to be constructed, even if no constructor of the object’s class is invoked for the initialization.
And
[class.dtor]/12
A destructor is invoked implicitly
for a constructed object with static storage duration (6.7.1) at program termination (6.6.4),
...
When an exception is thrown from a constructor, the object's initialization is not completed, the object is not deemed constructed and no destructor is called since there is infact no object.
Why is an object's destructor not called when an exception is thrown from its constructor?
Logically: because it was never constructed, so there's nothing to destroy.
An object's lifetime only begins when the constructor completes successfully.
Practically: if you throw an exception part-way through construction, how would a destructor know which parts of the object were created (and should be destroyed), and which are just un-initialized memory? This scheme could not possibly work.
So, the destructor can't be used to "undo" a failed constructor; it's automatically handled as part of stack unwinding instead. For example, consider:
class A;
class B;
class C;
class D : public A, B {
C m_c;
D() : A(), B(), m_c() {}
};
first, storage is allocated for D. If this step is dynamic, and fails, std::bad_alloc is thrown (and the D instance never started existing)
then A::A() initializes the first (A) base-class subobject. If this fails, the subobject never started existing, the storage allocation is unwound, etc.
if A::A() succeeds, B::B() initializes the second base-class subobject. If this throws, A::~A() is automatically used to destroy the A subobject.
if both base-class subobjects succeed, C::C() is used to initialize the member object: if this throws, both the A and B base-class subobjects are destroyed in reverse order
if all the A, B and C subobjects were constructed normally, only then is the body of D::D() (the part inside the {}, after the initializer list) entered. If this throws, the C, B and A objects are destroyed (in that order: it's always reverse order of construction)
only if all those steps succeed, a new instance of D has started its lifetime. This will be destroyed with D::~D() when its lifetime ends.
UKMonkey is right. See his comment.
As you raised an exception in constructor, it could not instantiate the object m. As no object exist so no call to destructor. That is the reason we must be very careful while throwing exception from a constructor. Just comment out throw 0; and check. You will understand it.
On the last line of a destructor, I have a diagnostic type message which takes a printf-like form:
"object destroyed at %p", this
I have concerns though about how well this is defined at such a point.
Should I have such reservations? Is the behaviour well-defined?
According to the C++ Standard (12.4 Destructors)
8 After executing the body of the destructor and destroying any
automatic objects allocated within the body, a destructor for class
X calls the destructors for X’s direct non-variant non-static data
members, the destructors for X’s direct base classes and, if X is the
type of the most derived class (12.6.2), its destructor calls the
destructors for X’s virtual base classes.
So your code is well-formed. All destructors of non-static data members and base classes are called after executing the body of the destructor.
Well, the pointer itself certainly still exists (it's just an address, after all). There should be no problem to print the pointer value.
On the other hand, everything that you did in the destructor has already happened. Attributes may already have been delete'd, etc, so you have to avoid anything that accesses those.
This has perfectly well defined behaviour. Consider that the this pointer can be used implicitly or explicitly throughout the destructor, e.g. whenever you access a member variable for things like delete ptr_;. After the destructor returns, the members are destroyed in reverse order of declaration/creation then the base destructors invoked.
As you might now, you can access your class members from the destructor. This would not be working if the this pointer was invalid. So you can safely assume that the address this points to is still the same that you might have printed in the constructor.
Inside the destructor the this pointer is well defined, as are all the members and bases (that will be destroyed in construction reverse order after the destructor return). So printing the address it refers is not UB.
The only thing is that the object itself cannot be assumed anymore as "polymorphic", since the derived components had already been destroyed.
class A
{
public:
virtual void fn() { std::cout << "A::fn" << std::endl; }
virtual ~A() { fn(); } //< will call A::fn(), even if B is destroying
};
class B: public A
{
public:
virtual void fn() { std::cout << "B::fn" << std::endl; }
virtual ~B() {}
};
int main()
{
B b;
A& a = b;
a.fn(); //< will print B::fn(), being A::fn virtual and being B the runtime-type of the a's referred object
return 0; //< will print A::fn() from b's A's component destructor
}
I have the following code:
struct Message
{
explicit Message(const std::string& message) : selfMessage(message) {};
~Message() { std::cerr << "Message: " << selfMessage << std::endl; }
const std::string selfMessage;
};
struct Foo
{
Foo() : fooMessage("Foo") {}
/// Destructor here is left intentionally non-virtual !!!
~Foo() { std::cerr << "~Foo" << std::endl; }
Message fooMessage;
};
struct Bar : Foo
{
Bar() : barMessage("Bar") {}
~Bar() { std::cerr << "~Bar" << std::endl; }
Message barMessage;
};
int main()
{
std::auto_ptr<Foo> foo(new Bar);
}
I expect the following output:
Message: Bar
Message: Foo
~Foo()
But actually (the code is compiled with gcc) does not print Message: Bar so as far as I understand barMessage is not destructed correctly. Why?
AFAIK non virtual d-tor affects only on the call of dtor of derived class - it will be never called, but what about stack-allocated members of derived class?
Thank you,
P.S. I already know about deprecated std::auto_ptr<>() usage :)
If you call delete on a derived object through a pointer to a base class object then you get undefined behavior unless the destructor of the base class is declared virtual.
Letting an std::auto_ptr templated on a base class go out of scope when it owns a derived class object has the effect of calling delete on a base class pointer type when the actual object is of a derived class type.
Ultimately, auto_ptr calls delete myPtr (where myPtr is a member
of type T*). Invoking delete where the static type and the dynamic
type are not the same is undefined behavior. It's not just a case where
the derived class destructors will not be called; it's a case where just
about anything can happen. And does, in cases of more complex
inheritance hierarchies.
This is only relevant for dynamically allocated instances. Invoking
delete on something which wasn't dynamically allocated is undefined
behavior (and will typically cause all sorts of problems). And except
for delete, the destructor is called on an object, not a pointer, so the
static type and the dynamic type are identical.
Bar::barMessage is not destructed precisely because the destructos of the base is not virtual. The pointer is of type Foo, and on exiting of the scope, the std::auto_ptr dill call delete on the internal pointer, which is Undefined behavior, and in this case will destroy only the Foo subobject.
Note that there is no such thing as stack allocated members of Bar, there are members with automatic storage, but in this case as the whole object has been dynamically allocated, that is not in the stack but in the heap (C++ technically has no concept of stack/heap but understand that all the Bar object is dynamically allocated)
With regards to the sample code below, why is the destructor for the base class called twice?
class Base {
public:
Base() {
std::cout << "Base::Base()" << std::endl;
}
~Base() {
std::cout << "Base::~Base()" << std::endl;
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived::Derived()" << std::endl;
}
~Derived() {
std::cout << "Derived::~Derived()" << std::endl;
}
};
int main() {
Base a = Derived();
return EXIT_SUCCESS;
}
Here is a sample of the output when the program is run:
Base::Base()
Derived::Derived()
Derived::~Derived()
Base::~Base()
Base::~Base()
What happens is called slicing. You initialize an object of type Base with an object of type Derived. Since any object of type Derived has also an object of type Base contained (called "base-class sub-object"), there will be two Base objects and one Derived object in existance throughout the program. The Derived object (and its base-class sub-object of type Base) only exists for the time of initialization, while the remaining Base object exists until end of main.
Since there are two Base objects and one Derived object, you will also see one more Base destructors run.
A copy constructor is being used. If you want to see what is going on, instrument the copy constructor too:
Base( const Base & ) {
std::cout << "Base::Base( const Base &)" << std::endl;
}
and similarly for Derived.
Note that this has NOTHING to do with the destructors not being virtual.
When you say Derived() in main() it creates a temporary object which is then copied into object a. Hence there are two objects because of which destructor is called twice. Also, as others pointed out your base class destructor should be virtual.
Because you create a temporary of type Derived before copy-constructing a with it. So this is basically what happens:
Derived d(); // Your temporary of type Derived is created
Base a(d); // The temporary is used to call a's copy constructor
d.Derived::~Derived(); // The temporary is destroyed, calling both ~Derived and ~Base
a.Base::~Base(); // The nonvirtual destructor on a is called, so ~Base is called, but not ~Derived
So apart from the unnecessary copying at the beginning (which the compiler may optimize away), the actual error is that ~Base isn't virtual.
Edit
Oops, completely missed the slicing that takes place as litb pointed out. Read his answer instead :)
Adding in the following will make the program more clear:
Base(const Base& base){
std::cout << "Base::Base(const Base& base)" << std::endl;
}
The compiler will automatically create a copy constructor for you. By defining it yourself, (and by adding in the print) you can see that the number of constructors and destructors match
Base::Base()
Derived::Derived()
Base::Base(const Base& base)
Derived::~Derived()
Base::~Base()
Base::~Base()
You need a virtual destructor.
You have one stack variable and one temporary - total of two objects constructed - so it's logical for the destructor to be called twice.
1) A temporary object of Derived type is built (Derived::Derived() and Base::Base() are called)
2) The temp object is copied into "a"
3) The temporary object is destroyed ( Derived::~Derived() and Base::~Base() are called)
4) return EXIT_SUCCESS;
5) "a" is destroyed, so Base::~Base() is called