TITLE: justification for exceptions (Newsgroups: comp.lang.c++.moderated, 20 Aug 98) CAPP: 0703460142-0001@t-online.de (Mike Capp) writes: > I hesitate to raise this one, as I have a sneaking suspicion that it > might be holy-war territory. But then, on the other hand, what the > hell. > > Could anyone suggest a reason why C++ exceptions are worth using? CLAMAGE: clamage@Eng.Sun.COM (Steve Clamage) C++ exceptions were designed to be most useful for the case when an unexpected error occurs at a significant "distance" from any code that can possibly handle it. Example: You have multiple levels of function calls dealing with file operations, and an operation deep in the heirarchy fails. What should be done? Possibilities range from simple retry to aborting the program to starting over from the beginning with a new file or device. The low-level function cannot make a decision because it doesn't have enough information. It can't do anything complicated because it doesn't have enough context, and you need to walk back up the call stack before starting over anyhow. Without exceptions, you must pass status codes throughout all the functions involved, checking at each stage whether to continue or immediately return to caller. The code that deals with unexpected errors overwhelms the code that does the ordinary operations. With exceptions, you designate the locations that will deal with errors (catch clauses), and the remainder of the code consists only of normal processing. When an unexpected situation is detected, you need one throw-statement and nothing else. The compiler and runtime system do everything else for you. It's important to understand appropriate and inappropriate uses of exceptions. Don't use them for ordinary control flow -- they constitute too much mechanism for that. Do use them for situations such as I outlined above. Here's another example: The default behavior according to the new standard for memory allocation using a new-expression is for a bad_alloc exception to be thrown if allocation fails. (The old behavior was to return a null pointer.) Programmers know that you should check the return from new (or malloc), but typically don't -- it clutters up the code. If allocation does fail, the program then exhibits bizarre behavior and probably crashes at a point far removed from the allocation failure. It takes a long time to find the problem. Under the new rules, the program will abort immediately if allocation fails and you don't check for failure with a try-block and catch-clause. You can find the point immediately when running under the debugger. Alternatively, you can add less-intrusive error checks: try { ptr = new T; ... lots of processing ... return something; // normal return } catch(bad_alloc) { ... indicate or handle allocation failure } The "lots of processing" is the normal code you had before. (Private email) TRIBBLE: David R Tribble Exceptions also automatically call the destructors for auto (stack) objects. This is something that non-local goto mechanisms (such as longjmp()) cannot do. The side effects of not destructing such objects can be catastrophic, since you're left with allocated but unreferenced resources, and you've lost all context information for them. The automatic cleanup that exceptions provide for you is what makes exception handling so expensive. So like Steve said, exceptions are not meant to be used everywhere, only at sufficiently "distant" levels of code.