DiscussionIt's no coincidence that most modern languages created in the past 20 years use exceptions as their primary error reporting mechanism. Almost by definition, exceptions are for reporting exceptions to normal processingalso known as "errors," defined in Item 70 as violations of preconditions, postconditions, and invariants. Like all error reporting, exceptions should not arise during normal successful operation. We will use the term "status codes" to cover all forms of reporting status via codes (including return codes, errno, a GetLastError function, and other strategies to return or retrieve codes), and "error codes" specifically for status codes that signify errors. In C++, reporting errors via exceptions has clear advantages over reporting them via error codes, all of which make your code more robust:
The main potential drawback of exception handling is that it requires programmers to be familiar with a few recurring idioms that arise from exceptions' out-of-band control flow. For example, destructors and deallocation functions must not fail (see Item 51), and intervening code must be correct in the face of exceptions (see Item 71 and References); to achieve the latter, a common coding idiom is to perform all the work that might emit an exception safely off to the side and only then, when you know that the real work has succeeded, you commit and modify the program state using only operations that provide the no-fail guarantee (see Item 51 and [Sutter00] §9-10, §13). But then using error codes also has its own idioms; those have just been around longer and so more people already know thembut, unfortunately, also commonly and routinely ignore them. Caveat emptor. Performance is not normally a drawback of exception handling. First, note that you should turn always on exception handling in your compiler even if it is off by default, otherwise you won't get standard behavior and error reporting from the C++ language operations such as operator new and standard library operations such as STL container insertions (see Exceptions). [Aside: Turning on exception handling can be implemented so that it increases the size of your executable image (this part is unavoidable) but incurs zero or near-zero performance overhead in the case where no exception is thrown, and some compilers do so. Other compilers do incur overhead, especially when providing secure modes to prevent malicious code from attacking the exception handling mechanism via buffer overruns. Whether there is overhead or not, at minimum do always at least turn on your compiler's support for exception handling, because otherwise the language and standard library won't report errors correctly. We mention this because we know of projects that turn off exception handling, which is a far-reaching fundamental decision and should never be done except as a last resort and with extreme care (see Exceptions).] Once your compiler's support for exception handling is turned on, the performance difference between throwing an exception and returning an error code is typically negligible in normal processing (the case where no error occurs). You may notice a performance difference in the case where an error does occur, but if you're throwing so frequently that the exception throwing/catching handling performance overhead is actually noticeable, you're almost certainly using exceptions for conditions that are not true errors and therefore not correctly distinguishing between errors and non-errors (see Item 70). If they're really errors that truly violate pre- and postconditions and invariants, and if they're really happening that frequently, the application has far more serious problems. One symptom of error code overuse is when application code needs to check relentlessly for trivially true conditions, or (worse) fails to check error codes that it should check. One symptom of exception overuse is when application code throws and catches exceptions so frequently that a TRy block's success count and failure count are within the same order of magnitude. Such a catch block is either not really handling a true error (one that violates preconditions, postconditions, or invariants), or the program is in serious trouble. |