Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dispatching exceptions in C++

Tags:

c++

oop

exception

How should exceptions be dispatched so that error handling and diagnostics can be handled in a centralized, user-friendly manner?

For example:

  • A DataHW class handles communication with some data acquisition hardware.
  • The DataHW class may throw exceptions based on a number of possible errors: intermittent signal, no signal, CRC failure, driver error. Each type of error gets its own exception class.
  • The DataHW class is called by a number of different pieces of code that do different types of acquisition and analysis.

The proper error handling strategy depends on the type of exception and the operation being attempted. (On intermittent signal, retry X times then tell the user; on a driver error, log an error and restart the driver; etc.) How should this error handling strategy be invoked?

  • Coding error recovery into each exception class: This would result in exception classes that are rather large and contain high-level UI and system management code. This seems bad.
  • Providing a separate catch block for each type of exception: Since the DataHW class is called from many different places, each catch block would have to be duplicated at each call site. This seems bad.
  • Using a single catch block that calls some ExceptionDispatch function with a giant RTTI-based switch statement: RTTI and switch usually indicates a failure to apply OO design, but this seems the least bad alternative.
like image 274
Josh Kelley Avatar asked Jul 15 '26 17:07

Josh Kelley


2 Answers

Avoid duplicating the catch blocks at each call site by catching (...) and calling a shared handler function which rethrows and dispatches:

f()
{
    try
    {
        // something
    }
    catch (...)
    {
        handle();
    }
}

void handle()
{
    try
    {
        throw;
    }
    catch (const Foo& e)
    {
        // handle Foo
    }
    catch (const Bar& e)
    {
        // handle Bar
    }
    // etc
}
like image 86
fizzer Avatar answered Jul 18 '26 05:07

fizzer


An idea I keep running into is that exceptions should be caught by levels which can handle them. For example, a CRC error might be caught by the function that transmits the data, and upon catching this exception, it might try to retransmit, whereas a "no signal" exception might be caught in a higher level and drop or delay the whole operation.

But my guess is that most of these exceptions will be caught around the same function. It is a good idea to catch and handle them seperately (as in soln #2), but you say this causes a lot of duplicate code (leading to soln #3.)

My question is, if there is a lot of code to duplicate, why not make it into a function?

I'm thinking along the lines of...

void SendData(DataHW* data, Destination *dest)
{
    try {
        data->send(dest);
    } catch (CRCError) {
        //log error

        //retransmit:
        data->send(dest);
    } catch (UnrecoverableError) {
        throw GivingUp;
    }
}

I guess it would be like your ExceptionDispatch() function, only instead of switching on the exception type, it would wrap the exception-generating call itself and catch the exceptions.

Of course, this function is overly simplified - you might need a whole wrapper class around DataHW; but my point is, it would be a good idea to have a centralized point around which all DataHW exceptions are handled - if the way different users of the class would handle them are similar.

like image 35
aib Avatar answered Jul 18 '26 07:07

aib