diff --git a/more/error_handling.html b/more/error_handling.html index f5798e7d51..b6d68ec556 100644 --- a/more/error_handling.html +++ b/more/error_handling.html @@ -63,14 +63,13 @@ catch(...), see below.
  • - Don't embed a std::string object or any other - data member or base class whose copy constructor could throw - an exception. That could lead to directly to std::terminate() - at the throw point. Similarly, it's a bad idea to use a base - or member whose ordinary constructor(s) might throw, because, - though not necessarily fatal to your program, you may report a - different exception than intended from a - throw-expression that includes construction such as: + Don't embed a std::string object or any other data + member or base class whose copy constructor could throw an exception. + That could lead directly to std::terminate() at the throw point. + Similarly, it's a bad idea to use a base or member whose ordinary + constructor(s) might throw, because, though not necessarily fatal to + your program, you may report a different exception than intended from + a throw-expression that includes construction such as:
    @@ -95,31 +94,29 @@ throw some_exception();
           that you have a fallback in case the formatting code throws
  • Don't worry too much about the what() - message. It's nice to have a message that a programmer - stands a chance of figuring out, but you're very unlikely to be - able to compose a relevant and user-comprehensible error - message at the point an exception is thrown. Certainly, - internationalization is beyond the scope of the exception class - author. Peter Dimov makes an excellent - argument that the proper use of a what() string is - to serve as a key into a table of error message formatters. Now - if only we could get standardized what() strings - for exceptions thrown by the standard library...
  • - -
  • Expose relevant information about the cause of the - error in your exception class' public interface. A fixation - on the what() message is likely to mean that you - neglect to expose information someone might need in order to - make a coherent message for users. For example, if your - exception reports a numeric range error, it's important to have - the actual numbers involved available as numbers in the - exception class' public interface where error reporting code can - do something intelligent with them. If you only expose a - textual representation of those numbers in - the what() string, you will make life very - difficult for programmers who need to do something more - (e.g. subtraction) with them than dumb output. + message. It's nice to have a message that a programmer stands a + chance of figuring out, but you're very unlikely to be able to compose + a relevant and user-comprehensible error message at the point an + exception is thrown. Certainly, internationalization is beyond the + scope of the exception class author. Peter Dimov makes an excellent argument + that the proper use of a what() string is to serve as a + key into a table of error message formatters. Now if only we could get + standardized what() strings for exceptions thrown by the + standard library...
  • + +
  • Expose relevant information about the cause of the error in + your exception class' public interface. A fixation on the + what() message is likely to mean that you neglect to + expose information someone might need in order to make a coherent + message for users. For example, if your exception reports a numeric + range error, it's important to have the actual numbers involved + available as numbers in the exception class' public interface + where error reporting code can do something intelligent with them. If + you only expose a textual representation of those numbers in the + what() string, you will make life very difficult for + programmers who need to do something more (e.g. subtraction) with them + than dumb output.
  • Make your exception class immune to double-destruction if possible. Unfortunately, several popular compilers occasionally cause @@ -136,15 +133,15 @@ throw some_exception(); where the problem was detected. That usually means assert() or something like it.

    -

    Sometimes it is necessary to have resilient APIs which can stand up - to nearly any kind of client abuse, but there is usually a significant - cost to this approach. For example, it usually requires that each object - used by a client be tracked so that it can be checked for validity. If - you need that sort of protection, it can usually be provided as a layer - on top of a simpler API. Beware half-measures, though. An API which - promises resilience against some, but not all abuse is an invitation to - disaster. Clients will begin to rely on the protection and their - expectations will grow to cover unprotected parts of the interface.

    +

    Sometimes it is necessary to have resilient APIs which can stand up to + nearly any kind of client abuse, but there is usually a significant cost + to this approach. For example, it usually requires that each object used + by a client be tracked so that it can be checked for validity. If you + need that sort of protection, it can usually be provided as a layer on + top of a simpler API. Beware half-measures, though. An API which promises + resilience against some, but not all abuse is an invitation to disaster. + Clients will begin to rely on the protection and their expectations will + grow to cover unprotected parts of the interface.

    Note for Windows developers: unfortunately, the native exception-handling used by most Windows compilers actually throws an @@ -187,27 +184,24 @@ extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*) usual safe assumptions that destructors and catch blocks have taken valid steps to ensure program invariants during unwinding. -

    I reluctantly concede this point to Hillel Y. Sims, who beat it - into me (<wink>): until all OSes are "fixed", if every - exception were derived from - std::exception and everyone substituted +

    I reluctantly concede this point to Hillel Y. Sims, who beat it into + me (<wink>): until all OSes are "fixed", if every exception were + derived from std::exception and everyone substituted catch(std::exception&) for catch(...), the - world would be a better place. - -

    Sometimes, catch(...), is still the most - appropriate pattern, in spite of bad interactions with OS/platform - design choices. If you have no idea what kind of exception might - be thrown and you really must stop unwinding it's probably - still your best bet. One obvious place where this occurs is at - language boundaries. + world would be a better place.

    +

    Sometimes, catch(...), is still the most appropriate + pattern, in spite of bad interactions with OS/platform design choices. If + you have no idea what kind of exception might be thrown and you really + must stop unwinding it's probably still your best bet. One obvious + place where this occurs is at language boundaries.


    -

    © Copyright David Abrahams 2001-2003. Permission to copy, - use, modify, sell and distribute this document is granted provided - this copyright notice appears in all copies. This document is - provided "as is" without express or implied warranty, and with no - claim as to its suitability for any purpose.

    +

    © Copyright David Abrahams 2001-2003. Permission to copy, use, + modify, sell and distribute this document is granted provided this + copyright notice appears in all copies. This document is provided "as is" + without express or implied warranty, and with no claim as to its + suitability for any purpose.

    Revised