Просмотр исходного кода

updated guidelines

[SVN r18047]
Dave Abrahams 23 лет назад
Родитель
Сommit
52f3862c6c
1 измененных файлов с 126 добавлено и 26 удалено
  1. 126 26
      more/error_handling.html

+ 126 - 26
more/error_handling.html

@@ -1,15 +1,22 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
-    <meta name="generator" content="HTML Tidy, see www.w3.org">
-    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+
+<html>
+  <head>
+    <meta name="generator" content=
+    "HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
+    <meta http-equiv="Content-Type" content=
+    "text/html; charset=windows-1252">
 
     <title>Error and Exception Handling</title>
+  </head>
 
+  <body>
     <h1>Error and Exception Handling</h1>
 
     <h2>References</h2>
 
     <p>The following paper is a good introduction to some of the issues of
-    writing robust generic components:
+    writing robust generic components:</p>
 
     <blockquote>
       <a href="generic_exception_safety.html">D. Abrahams: ``Exception Safety
@@ -24,7 +31,7 @@
     <h3>When should I use exceptions?</h3>
 
     <p>The simple answer is: ``whenever the semantic and performance
-    characteristics of exceptions are appropriate.''
+    characteristics of exceptions are appropriate.''</p>
 
     <p>An oft-cited guideline is to ask yourself the question ``is this an
     exceptional (or unexpected) situation?'' This guideline has an attractive
@@ -32,7 +39,7 @@
     ``exceptional'' is another's ``expected'': when you really look at the
     terms carefully, the distinction evaporates and you're left with no
     guideline. After all, if you check for an error condition, then in some
-    sense you expect it to happen, or the check is wasted code.
+    sense you expect it to happen, or the check is wasted code.</p>
 
     <p>A more appropriate question to ask is: ``do we want stack unwinding
     here?'' Because actually handling an exception is likely to be
@@ -40,9 +47,70 @@
     ``Can I afford stack unwinding here?'' For example, a desktop application
     performing a long computation might periodically check to see whether the
     user had pressed a cancel button. Throwing an exception could allow the
-    operation to be cancelled gracefully. On the other hand, it would probably
-    be inappropriate to throw and <i>handle</i> exceptions in the inner loop of
-    this computation because that would have a significant performance impact.
+    operation to be cancelled gracefully. On the other hand, it would
+    probably be inappropriate to throw and <i>handle</i> exceptions in the
+    inner loop of this computation because that could have a significant
+    performance impact.</p>
+
+    <h3>How should I design my exception classes?</h3>
+
+    <ol>
+      <li><b>Inherit from <code>std::exception</code></b>. Except in *very*
+      rare circumstances where you can't afford the cost of a virtual table,
+      <code>std::exception</code> makes a reasonable exception base class,
+      and when used universally, allows programmers to catch "everything"
+      without resorting to <code>catch(...)</code>. For more about
+      <code>catch(...)</code>, see below.</li>
+
+      <li>
+        <b><i>Don't</i> embed a std::string object</b> or any other data
+        member or base class whose copy constructor could throw an exception.
+        That could lead to termination during stack unwinding. Similarly,
+        it's a bad idea to use a base or member whose ordinary constructor
+        might throw, because, though not fatal, you will report a different
+        exception than intended when that happens in a
+        <i>throw-expression</i> such as: 
+
+        <blockquote>
+<pre>
+throw some_exception();    
+</pre>
+        </blockquote>
+
+        <p>There are various ways to avoid copying string objects when
+        exceptions are copied, including embedding a fixed-length buffer in
+        the exception object, or managing strings via reference-counting.
+        However, consider the next point before pursuing either of these
+        approaches.</p>
+      </li>
+
+      <li><b>Format the <code>what()</code> message on demand</b>, if you
+      feel you really must format the message. Formatting an exception error
+      message is typically a memory-intensive operation that could
+      potentially throw an exception. This is an operation best delayed until
+      after stack unwinding has occurred, and presumably, released some
+      resources. It's a good idea in this case to protect your
+      <code>what()</code> function with a <code>catch(...)</code> block so
+      that you have a fallback in case the formatting code throws</li>
+
+      <li><b>Don't worry <i>too</i> much about the <code>what()</code>
+      message</b>. 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 <i>user</i>-comprehensible error message at the point an
+      exception is thrown. Certainly, internationalization is beyond the
+      scope of the exception class author. <a href=
+      "../people/peter_dimov.htm">Peter Dimov</a> makes an excellent argument
+      that the proper use of a <code>what()</code> string is to serve as a
+      key into a table of error messages. Now if only we could get
+      standardized <code>what()</code> strings for exceptions thrown by the
+      standard library...</li>
+
+      <li><b>Make your exception class immune to double-destruction</b> if
+      possible. Unfortunately, several popular compilers occasionally cause
+      exception objects to be destroyed twice. If you can arrange for that to
+      be harmless (e.g. by zeroing deleted pointers) your code will be more
+      robust.</li>
+    </ol>
 
     <h3>What About Programmer Errors?</h3>
 
@@ -50,26 +118,27 @@
     using, I don't want stack unwinding. What I want is a core dump or the
     equivalent - a way to inspect the state of the program at the exact point
     where the problem was detected. That usually means <tt>assert()</tt> or
-    something like it.
-
-    <p>Sometimes it is neccessary 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.
+    something like it.</p>
+
+    <p>Sometimes it is neccessary 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.</p>
 
     <p><b>Note for Windows developers</b>: unfortunately, the native
     exception-handling used by most Windows compilers actually throws an
     exception when you use <tt>assert()</tt>. Actually, this is true of other
     programmer errors such as segmentation faults and divide-by-zero errors.
     One problem with this is that if you use JIT (Just In Time) debugging,
-    there will be collateral exception-unwinding before the debugger comes up.
-    Fortunately, there is a simple but little-known workaround, which is to use
-    the following incantation:
+    there will be collateral exception-unwinding before the debugger comes up
+    because <code>catch(...)</code> will catch these not-really-C++
+    exceptions. Fortunately, there is a simple but little-known workaround,
+    which is to use the following incantation:</p>
 
     <blockquote>
 <pre>
@@ -81,12 +150,43 @@ extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)
          = _set_se_translator(straight_to_debugger);
 </pre>
     </blockquote>
+    This technique doesn't work if the SEH is raised from within a catch
+    block (or a function called from within a catch block), but it still
+    eliminates the vast majority of JIT-masking problems. 
+
+    <h3>How should I handle exceptions?</h3>
+
+    <p>Often the best way to deal with exceptions is to not handle them at
+    all. If you can let them pass through your code and allow destructors to
+    handle cleanup, your code will be cleaner.</p>
+
+    <h4>Avoid <code>catch(...)</code> when possible</h4>
+    Unfortunately, operating systems other than Windows also wind non-C++
+    "exceptions" (such as thread cancellation) into the C++ EH machinery, and
+    there is sometimes no workaround corresponding to the
+    <code>_set_se_translator</code> hack described above. The result is that
+    <code>catch(...)</code> can have the effect of making some unexpected
+    system notification at a point where recovery is impossible look just
+    like a C++ exception thrown from a reasonable place, invalidating the
+    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 (&lt;wink&gt;):
+    until all OSes are "fixed", if every exception were derived from
+    <code>std::exception</code> and everyone substituted
+    <code>catch(std::exception&amp;)</code> for <code>catch(...)</code>, the
+    world would be a better place. 
     <hr>
 
     <p>&copy; Copyright David Abrahams 2001. 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. 
+    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.</p>
 
     <p>Revised 
-    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->19 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34359" -->
+    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->
+     22 March, 2003<!--webbot bot="Timestamp" endspan i-checksum="34359" -->
+    </p>
+  </body>
+</html>
+

粤ICP备19079148号