Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Project with well designed exception mechanism

Tags:

c++

exception

Does anyone know a opensource c++ application with a well designed/robust exception mechanism so I can get some inspiration? Most code/examples I see do questionable things like:

  1. Throw objects with a message string as argument. Seems wrong because it marks the exception as fatal, a error message wich can be displayed to the user higher up leaves little room for client code trying to handle the exception. Even if the exception is fatal, things like diffirent locales (languages) makes formatting a message at the point of throw seem like a bad idea to me.
  2. Use tons of different exception classes derived from a base exception class. Just feels wrong introducing a new class/type for every single thing that can go wrong (open file, read file, write file, create thread, etc...). Catching all unhandled exceptions at the highest level using the base type loses type information required to display meaningfull error messages.
  3. Use one exception class derived from a base exception class for every component/library and give it a error code as argument to indicate the exact error. Catching with base type results in ambiguity. (Whose error code "3" did we catch? )...

Some pointers in the right direction would be welcome.

like image 806
Unimportant Avatar asked Apr 25 '12 23:04

Unimportant


1 Answers

To address all three of these, I found that the best for me is to throw my own custom exception that's derived from std::runtime_error. Like this:

#include <exception>

class ChrisAException : public std::runtime_error
{
      /// constructor only which passes message to base class
      ChrisAException(std::string msg)
      : std::runtime_error(msg)
      {

      }
}

It allows accepting a string, which I always put in something like the following format (assuming x negative was not a valid input and meant something calling it was in error):

#include "ChrisAException.h"

void myfunction(int x)
{

    if(x < 0) 
    {
        throw ChrisAException("myfunction(): input was negative!");
    }

    // rest of your function
} 

For this one, keep in mind that the strings in these exceptions are more for the programmer than the end user. It's the programmer of the interface's job to display something meaningful in the locale when there's a failure. The strings in the exception can either be logged or seen at debug time (preferable!)

This way you can ultimately catch it with:

try
{
      // high level code ultimately calling myfunction

}
catch(ChrisAException &cae)
{
       // then log cae.what()
}
catch(std::runtime_error &e)
{
       // this will also catch ChrisAException's if the above block wasn't there
}
catch(...)
{
      // caught something unknown
}

I personally don't like deriving too many types of exceptions, or giving an error code. I let the string message do the reporting.

In general, I use C++ exceptions to mean "something went wrong with the program" and not to handle normal use cases. Thus, for me, a thrown exception during the algorithm execution either means "flag the user that something went wrong" or "don't tell the user" (depending on how critical that code was to what they were doing) but certainly log it and let the programmers know somehow.

I don't use C++ exceptions to handle cases that aren't essentially programming errors, e.g., some kind of incorrect logic or something being called wrong. For example, I wouldn't use C++ exceptions to handle normal program situations like an empty DVD not being in the drive for a DVD writing program. For that, I'd have explicit return code that allows the user to know whether an empty DVD was there (maybe with a dialog etc.)

Keep in mind that part of C++ exception handling is to unwind the stack up to a try-catch block. To me that means, abort what's going on in the program and clean up the stack. In the case of something like my DVD example, you shouldn't really want to unwind much of the stack. It wasn't catastrophic. You should simply let the user know and then let them try again.

But again, this is my preferred way of using C++ exceptions, based on experience and my reading. I'm open to opinions otherwise.

edit: Changed std::exception to std::runtime_error based on commenter advice.

like image 191
Chris A. Avatar answered Oct 13 '22 00:10

Chris A.