Exceptions vs. Error Return Codes

I have been partly responsible for maintaining legacy source code. Almost all of the code is implemented in C and therefore does not use exceptions. Much of the error handling code follows the following pattern here implemented in C++ (imagine in this example, operator new returns 0 when no memory is available):

int function()
{
  MyTypeA * ptrValTypeA = 0;
  MyTypeB * ptrValTypeB = 0;

  ptrValTypeA = new MyTypeA();
  if(ptrValTypeA == 0)
  {
    /* error handling #1 */
    return -1; /* error, no memory */
  }

  ptrValTypeB = new MyTypeB();
  if(ptrValTypeB == 0)
  {
    /* error handling #2 */
    delete ptrValTypeA;
    return -1; /* error, no memory */
  }

  /* ... more code ... */

  if(function_call() == -1)
  {
    /* error handling #3 */
    delete ptrValTypeA;
    delete ptrValTypeB;
    return -1;
  }

  /* ... even more code ... */

  return 0; /* no error */
}

The above code could be reduced to the following (assuming the default behavior of operator new throwing an exception when memory is exhausted):

int function()
{
  MyTypeA * ptrValTypeA = 0;
  MyTypeB * ptrValTypeB = 0;

  try
  {
    ptrValTypeA = new MyTypeA();
    ptrValTypeB = new MyTypeB();

    /* ... more code ... */

    if(function_call() == -1)
      throw Exception();

    /* ... even more code ... */
  }
  catch(...)
  {
    /* error handling */
    delete ptrValTypeA;
    delete ptrValTypeB;
    return -1;
  }
  return 0; /* no error */
}

Error handling in the first code snippet is spread to multiple places in the code. This makes the code less readable and therefore less maintainable.

The second code snippet shows that error handling is localized. The normal flow of the code is easy to follow, and freeing allocated resources is performed in one place when an exception occurs.

I am currently tasked with designing and implementing a C# software component. There are software developers who insist on adopting error return codes over exceptions because of unmeasured performance concerns. For example, some developers demand database connection timeouts or failures should use error return codes. My experience with error handling in legacy C code makes me resist error return codes and prefer exceptions.

If exceptions are used properly for exceptional cases such as an offline database, then the performance impact will be rarely realized and the code can be cleanly written. A performance hit that only happens during unexpected or abnormal operation is a good trade for clean code without the cost of constant error checking during normal operation.

For further reading, see Why Exceptions Should Be Exceptional.

Questions, comments, and responses are welcomed and appreciated.

Leave a Reply