The article Exception Handling: A False Sense of Security , written by Tom Cargill, was published in The C++ Report, volume 6, number 9, November-December 1994. As he explained to me in a private 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++’ [my italics].
In his view, the community underestimated the intricacies and overestimated the benefits of exceptions. Programming with exceptions in C++ is as difficult and, at the end of the day, as unsafe from a correctness perspective, as programming without them. He illustrated the point using a dynamic stack template class as running example. Let me summarise what I consider to be the article's general arguments:
The article's domain of interest was C++, but part of his criticisms are less determining due to the nature of C++. In particular, the third point above. Exception mechanisms may be judged relative to the programming language where they are supported—after all, efficiency and backwards-compatibility are main design goals of C++, not safety or correctness. However, from the title I expected a general description of the problems raised by exceptions. (There's fortunately some of that in the article.)
The problems involving memory management in his 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 are the problems with 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 adhere to the camp that considers programming languages better when they provide automatic support for tasks otherwise performed by the programmer. Just like we consider managing our own activation records a matter of the past, so we should consider memory management for general-purpose programming languages. Opposition to correctness in defence of technologically contingent notions of efficiency is striking. Between efficiency and maintainability, I chose the latter.
Nevertheless, given the design goals of C++, things will stay as they are, and Tom Cargill is quite right.
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’.