Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

destructor not called in case of exception with scoped_ptr

I have just started using c++ boost libraries. I read in many places that when a scoped_ptr is used then the object is always destroyed even in case of exceptions.

They behave much like built-in C++ pointers except that they automatically delete the object pointed to at the appropriate time. Smart pointers are particularly useful in the face of exceptions as they ensure proper destruction of dynamically allocated objects.

I tried in the following code.

#include<boost/scoped_ptr.hpp>

class B
{
  public:
    B(){ std::cout<< "B constructor call\n"; }
    ~B(){ std::cout<<"B destructor call\n"; }
};

class A
{
  public:
  boost::scoped_ptr<B> b;
  A():b(new B())  
  {
    throw 1;
  }
};

int main()
{
    A a; return 0;
}

output:
B constructor call
terminate called after throwing an instance of 'int'
Aborted (core dumped)

There is no call to B's destructor. But I used scoped_ptr so it should have called B's destructor or did I mis-interpreted the use of scoped_ptr.

But if a surround it with try catch then B's destructor is called.

try{
  A a;
} catch( ... ) {
}

In this case destructor of A will be called as all locally allocated objects in case of exception in a try block are removed from the stack and I have my pointer wrapped inside and object of scoped_ptr so when the destructor of scoped object destroys which ultimately the pointer. So is scoped_ptr is useful because we don't have to explicitly delete the memory allocated or I mis-interpreted the description of scoped_ptr.

How can I call the destructor of class B in case of exception using scoped_ptr

like image 448
leonidus Avatar asked Oct 14 '12 23:10

leonidus


People also ask

Are destructors called on exceptions?

Destructors are only called for the completely constructed objects. When the constructor of an object throws an exception, the destructor for that object is not called.

What happens when destructor is not called?

The destructor is called before the object is destroyed. Since you allocated the object with new , you must manually explicitly destroy it and deallocate the memory it occupied by calling delete on a pointer to the object.

Is destructor called when exception is thrown in constructor?

When an exception is thrown from a constructor, the object is not considered instantiated, and therefore its destructor will not be called. But all destructors of already successfully constructed base and member objects of the same master object will be called.

Can a destructor throw an exception?

The C++ rule is that you must never throw an exception from a destructor that is being called during the "stack unwinding" process of another exception.


1 Answers

There's no matching exception handler, so std::terminate is called directly, in this case without the stack being unwound. Put a try/catch in main that catches int and you'll see your destructor call, even if that handler rethrows.

C++11 §15.1/2:

When an exception is thrown, control is transferred to the nearest handler with a matching type; "nearest" means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited.

and §15.3/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.

Online demo

like image 50
ildjarn Avatar answered Sep 20 '22 12:09

ildjarn