Notes of Tom Cargill's
Exception Handling: A False Sense of Security

Pablo Nogueira

Updated: 4 Jul 2012


These type-written notes are personal reminders written to myself, not reviews nor abridgements. They may not make sense unless you've read the article.


Tom Cargill published Exception Handling: A False Sense of Security in The C++ Report, volume 6, number 9, November-December 1994. As he kindly explained to me by email, ‘at that time, a decade ago, the C++ community was generally optimistic that C++ exception handling was going to be a Good Thing. I wished to add a dose of reality—a reality that derives from the nature of C++’.

In Tom's view, the community underestimated the intricacies and overestimated the benefits of exceptions. Programming with exceptions in C++ is as difficult and, in the end, as unsafe from a correctness perspective as programming without them. He illustrated the point using a running example of a template class implementing a dynamic stack. Let me summarise what I consider to be the article's main general points:

  1. Exceptions require disciplined programming. For instance, entities might have to be left in the same state as they were previous to the occurrence of an exception. This imposes restrictions and careful analyses on what can be done before potential exception points.
  2. Exceptions make code harder to understand and maintain (‘spaghetti-code’ criticism).
  3. (Related to the previous point) Exceptions do not make code safer. We must be aware of exception points, of their interconnections, and of the interaction with other language features. This proves hard in C++ where there's problematic feature interaction (e.g., automatic and default behaviour). What's the point of writing a stack class using exceptions if the code introduces other correctness problems that exceptions do not catch?

The article's domain of interest was C++ and some of the criticisms were due to the nature that programming language (efficiency and backwards-compatibility weigh more in C++ than safety or correctness). However, from the title I expected a general discussion of the problems raised by exceptions. Fortunately, there's some of that in the article.

Exception mechanisms have to be judged relative to the programming language in which they are implemented. In fact, some might think that talk of exception mechanisms outside a programming language is nonsense.

The problems involving memory management in Tom's stack example (memory leaks and destructors) disappear with automatic garbage collection. In C++ objects can be passed to and returned from methods by reference or by value. In the latter case, constructors are called for temporaries. These are potential exception points, especially if there is dynamic allocation. It is easier to concentrate on explicit calls and disallow implicit construction (i.e., use references like Java). Finally, there's the problem of automatically defined methods. C++ does not require classes to be equipped with constructors, copy constructors, assignment, etc. Copy constructors and assignment operators more than often share much code. The former create and initialise, the latter clean-up, perhaps create, and initialise, and must take care of self-assignment. These requirements are not enforced by the language. They are left as post-it notes on the screen. It makes more sense to enforce them within the language than to use exceptions to cope with the consequences of unenforcement.

I believe programming languages are better when they provide automatic support for tasks otherwise performed by the programmer. We no longer manage activation records manually. Opposition to correctness in defence of technologically contingent notions of efficiency is striking. The trade-off between efficiency and maintainability should be resolved in favour of the latter.

Given the design goals of C++, things will stay as they are, and Tom's article hit the mark.

I asked Tom what he thought about functional languages. He replied: ‘Today, for a variety of reasons, I think that the weakest characteristic of imperative languages is control flow. I'm not ready to abandon imperative for functional, though. I'd prefer to see imperative languages acquire some notion of transaction. However, my understanding of what I really mean by this is still quite vague. I have a better sense of the problems that might be addressed by transactions than of a plausible set of control primitives’.