Just when you think you know everything about a programming language like C++, it will surprise you with new oddities.

I haven’t written any serious C++ code in a while but I used to be able to write it blindfolded. Yesterday, however, I came across a somewhat weird issue with exceptions that I am not sure makes a lot of sense.

Let’s assume you have a method foo and in there you have some code and inbetween you throw an exception, like this:

#include <iostream>
using namespace std;

void foo (void) {
  cout << "code before exception" << endl;
  throw 1;
  cout << "code after exception" << endl;
}

int main (int argc, char **argv) {
  try {
    foo ();
  } catch (int error) {
    cout << "exception caught" << endl;
  }

  return 0;
}

If you run this, you will of course only see the “code before exception” and “exception caught” messages.

Let’s add a local object to the scenario now, like this:

#include <iostream>
using namespace std;

class Object {
public:
  Object () {
    cout << "object constructed" << endl;
  }

  virtual ~Object () {
    cout << "object destroyed" << endl;
  }
};

void foo (void) {
  Object object;
  cout << "code before exception" << endl;
  throw 1;
  cout << "code after exception" << endl;
}

int main (int argc, char **argv) {
  try {
    foo ();
  } catch (int error) {
    cout << "exception caught" << endl;
  }

  return 0;
}

If you run the program this time, this is the output you will see:

object constructed
code before exception
object destroyed
exception caught

Notice how the object destructor is called properly as the object is local variable. It’s lifecycle ends when the program leaves foo().

Now, let’s change this again. We’ll throw an exception in the constructor and we’ll declare the local variable inbetween the code in foo():

#include <iostream>
using namespace std;

class Object {
public:
  Object () {
    cout << "object created" << endl;
    throw 1;
  };
  
  virtual ~Object () {
    cout << "object destroyed" << endl;
  }
};

void foo (void) {
  cout << "code before exception" << endl;
  Object object;
  cout << "code after exception" << endl;
}

int main (int argc, char **argv) {
  try {
    foo ();
  } catch (int error) {
    cout << "exception caught" << endl;
  }

  return 0;
}

Any guesses what output you will see now? Oddly enough, the local object will no longer be destroyed properly:

code before exception
object created
exception caught

So what does this mean?

  • Exceptions can make your applications leak memory. If large chunks of memory were allocated in the object constructor prior to the exception, they would not be released.
  • Exceptions in constructors are bad. If the code that can lead to the exception is moved into a normal method of Object instead of the constructor and if this method is called separately, the object will be destroyed properly.
  • Never be too sure about your knowledge of a certain programming language. There will be surprises. Always.