V509. The 'throw' operator inside the destructor should be placed within the try..catch block. Raising exception inside the destructor is illegal

11.07.2012

In case an exception is thrown in a C++ program stack unwinding begins which causes objects to be destroyed by calling their destructors. If a destructor invoked during stack unwinding throws another exception and that exception propagates outside the destructor the C++ runtime immediately terminates the program by calling terminate() function. Therefore destructors should never let exceptions propagate - each exception thrown within a destructor should be handled in that destructor.

The analyzer found a destructor containing the throw operator outside the try..catch block. Here is an example:

LocalStorage::~LocalStorage()
{
  ...
  if (!FooFree(m_index))
    throw Err("FooFree", GetLastError());
  ...
}

This code must be rewritten so that the programmer is informed about the error that has occurred in the destructor without using the exception mechanism. If the error is not crucial, it can be ignored:

LocalStorage::~LocalStorage()
{
  try {
    ...
    if (!FooFree(m_index))
      throw Err("FooFree", GetLastError());
    ...
  }
  catch (...)
  {
    assert(false);
  }
}

Exceptions may be thrown when calling the 'new' operator as well. If memory cannot be allocated, the 'bad_alloc' exception will be thrown. For example:

A::~A()
{
  ...
  int *localPointer = new int[MAX_SIZE];
  ...
}

An exception may be thrown when using dynamic_cast<Type> while handling references. If types cannot be cast, the 'bad_cast' exception will be thrown. For example:

B::~B()
{
  ...
  UserType &type = dynamic_cast<UserType&>(baseType);
  ...
}

To fix these errors you should rewrite the code so that 'new' or 'dynamic_cast' are put into the 'try{...}' block.

Additional materials on this topic:

You can look at examples of errors from real projects which were detected by this diagnostic message.