Search code examples
c++exceptiondestructorraii

Way for C++ destructor to skip work when specific exception being thrown?


I have an object on the stack for which I wish its destructor to skip some work when the destructor is being called because the stack is being unwound due to a specific exception being thrown through the scope of the object on the stack.

Now I could add a try catch block inside the scope of the stack item and catch the exception in question and notify the stack object to not run the work to be skipped an then rethrow the exception as follows:

RAII_Class pending;

try {
  doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
  pending.notifySkipResourceRelease();
  throw;
}

However, I'm hoping there is a more elegant way to do this. For example imagine:

RAII_Class::~RAII_Class {
  if (detectExceptionToSkipPendingDtorBeingThrown()) {
    return;
  }
  releaseResource();
}

Solution

  • You can almost do this with std::uncaught_exception(), but not quite.

    Herb Sutter explains the "almost" better than I do: http://www.gotw.ca/gotw/047.htm

    There are corner cases where std::uncaught_exception() returns true when called from a destructor but the object in question isn't actually being destroyed by the stack unwinding process.

    You're probably better off without RAII because it doesn't match your use case. RAII means always clean up; exception or not.

    What you want is much simpler: only release resource if an exception is not throw which is a simple sequence of functions.

    explicitAllocateResource();
    doSomeWorkThatMayThrowException();
    explicitReleaseResource(); // skipped if an exception is thrown
                               // by the previous function.