failing like never before

2Jun/130

Exceptions: A Tale of Love and Hate

I am very much a "C" style programmer, so exceptions are not something I use, or see on an everyday basis. Despite this, I've always had a love/hate relationship with exceptions, with my emotions depending on the situation I'm in.

In the past few years, I've used OCaml and Python on occasion to do some quick prototyping (and even some not-too-quick prototyping), and I found the languages' support for exceptions to be quite useful. Being able to call library functions without having to continuously check their return values, and instead be able to rely on the called functions to throw an exception when something bad happens, allows me to write much more quickly. Compare this, for example, to OpenCL in C (because C doesn't have exceptions), which I've been exploring recently. Even the most basic of OpenCL programs, to multiply two vectors, requires 50+ lines of boilerplate code, half of which is "if" statements checking to make sure a cl function didn't return -1. When I was writing my first OpenCL program, I was muttering in annoyance with how much boilerplate cruft I had to spew out and dreaming of exceptions. What I wanted, was for the cl functions to throw an exception on error, which would then allow me to have a single generic catch-all exception handler to dump some error messages and gracefully die.

But we shouldn't forget that exceptions have a place outside of simple prototyping also. Some level of terseness is always appreciated, especially when it allows the programmer to focus on the real task at hand, instead of writing an error check for every function call.

The real magic of exception handlers is that they allow the program to unwind the call stack all in one go, without actually having to jump to each and every return address on the stack as it goes. This is quite powerful, allowing the program to immediately handle the exception when it occurs, and removing the need for the programmer to organize her code to pass the error back up the call stack to where it can be processed.

But as Uncle Ben reminded us, with great power comes great responsibility. The power of exception handlers also gives programmers the ability to screw things up in remarkable ways. Because the exception basically forces a jump to the closest exception handler, all the code in between the exception and the handler won't get executed. This may include important bits like free() and close(), or even just simple things like finishing up printing parts of an output message. While the exception handler is *supposed* to handle all those bits, it's not uncommon for them to be forgotten. A common reason for this, is placing the exception handler very far away from where the exception might be thrown.

Which leads me nicely into my next story. I was working on a bug in some Python code last week, where an exception was thrown somewhere within several thousand lines of code and then handled way at the top of the program. The error message printed was "Exception occurred in <wubwubwub> server," making it quite possibly one of the most useless error messages of all time. I spent a good five minutes raging silently at the programming gods before trying to identify a root cause. It's important to remember that the point of exception handlers is to improve our lives not just in the short term, but also for the long term when code needs to be fixed and maintained.

There are of course many other reasons to love or hate exceptions. But these are the ones that strike a particular chord with me because of my limited experiences. I don't believe exceptions are totally bad, it is merely a powerful tool that is far too often misused, much like "goto" (let's not get ourselves muddled in that argument though...). My personal belief is that the power and terseness of exceptions is sufficient enough that it shouldn't be completely eschewed, but simply used sparingly and with great care. The problem with that idea of course, is that software development sits in the real world, not some lovey-dovey happy-place, where there is always plenty of time to work on projects, everyone is properly trained, all code is properly reviewed, and vampires sparkle in the sun.