5

I have a code such as this:

class myclass
{
     myclass()
     {
        // doing some init here
      }
     ~myclass()
     {
        // doing some important clean up here
     }
     void Do()
     {
          //    doing some work which may throw exception
      }
}

and I am using this class in this way:

MyFunction()
{
    myclass mc;
    mc.do();
 }

My question is :

If there is an exception in do function, what would happen? Is destructor of myclass called?

If no, what is the best way to handle this type of situations? Assume that I don't have the source code and I am sure about what is happening in destructor.

mans
  • 17,104
  • 45
  • 172
  • 321

3 Answers3

9

If there is an exception in do function, what would happen?

If you have any handler, it will be handled.

Is destructor of myclass called?

Yes, definitely. The standard quotes this::

An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.

This whole process is known as "stack unwinding":

The process of calling destructors for automatic objects constructed on the path from a try block to a throw-expression is called “stack unwinding.” If a destructor called during stack unwinding exits with an exception, std::terminate is called (15.5.1).

C++11 15.5.1 The std::terminate() function [except.terminate]

2 … In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called.

Abhineet
  • 5,320
  • 1
  • 25
  • 43
3

If the exception is caught somewhere, then stack unwinding will guarantee that the destructor is called for this object (and, in general, all automatic variables that go out of scope as a result of the exception). This is a very important guarantee, without which we could not use techniques like RAII to write exception-safe code.

If the exception is not caught, then the program will be terminated, and it's implementation-dependent whether or not the stack will be unwound first. If it's important to destroy the object cleanly even in that situation, then one option is to catch and rethrow the exception, outside the object's scope.

If the program is ended in some other way, e.g. by calling exit() or terminate(), or receiving an unhandled signal, then the stack won't be unwound. If you need clean destruction in these situations, then things will get messy.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

C++ does not have explicit "finally" clauses like many other languages, but instead you rely in "RAII" which essentially is a technique of using scoped "automatic" variables and relying on the fact that their destructor will get called at the appropriate moment when they go out of scope.

In your case the destructor of myclass will be called even if mc.do() throws an exception. In a lot of these "closure" issues, the object you put at the top of the scope block is a class that is used only for the purpose of invoking the destructor on termination.

The "D" language comes with a special closure syntax. There have been attempts to write libraries that do that in C++ and with lambdas it is certainly easier to write than now than it used to be although I do not think they are a formal part of C++ as yet.

CashCow
  • 30,981
  • 5
  • 61
  • 92