I’m hardly a behemoth of jollity back in the world of C++ at the moment. Much as a think it is an excellent language, I am reminded that is so open to abuse. Take the following example I recently stumbled across.

try
{
  ...
  ...

  throw "Floating point error"
  ...
  ...
}
catch(const char *e)
{
  string strError(e);
  if (strError == "floating point error")
  {
    ...
    ...
  }
  else if (strError == "some other error")
  {
    ...
    ...
  }
  else if (strError == "some violation")
  {
    ...
    ...
  }
  else throw;
}

Clearly this is open to all sorts of problems. Probably the most obvious it breaks when the string content changes due to capitalization and the floating point error never being seen. However, for me the most significant problem here is a fundamental misunderstanding of what exceptions are really all about.

The author of this code is trying to catch an exception based on its value and not its type. A string literal contains practically no information about the type of exception being thrown. It’s no different to using a string to represent a float or complex number. You can do it but you’d be making hard work for yourself.

And this isn’t confined to string literals. Throwing ints, floats or any predefined type has all the same issues. Once caught, there is no real type information, so you can’t be sure what it represents and have to jump through hoops to fathom how to deal with it –  the Temple of Doom!

I’m not going into a long technical treatise about C++ exceptions; there’s plenty of books and online material that cover it much better than I could. However here’s some bullet point reminders I tend to keep in my head for such occasions that are mostly obvious.

  • exception types are abstract data types representing an exceptions.
  • provide some standard method (what) that describes the exception and maybe a code.
  • better still, derive from a standard exception type. You can then catch the specific type or the base class type.
  • make sure you’ve got a non-throwing copy constructor and destructor in place.
  • don’t throw exception pointers. The address of the exception pointer will be somewhere on the heap and isn’t protected for the duration of the catch. A temporary stack based exception is guaranteed to be safely persisted until the exception has been handled, regardless of platform and compiler.
  • throw by value and catch by reference
    • you prevent unnecessary copying of large exception objects
    • you ensure that modifications applied to the exception within a catch clause are preserved in the exception object if it is re-thrown
    • you avoid slicing of derived exception objects
    • you’ve got less work to do!

As Short Round said – “I keep telling you, you listen to me more, you live longer!”