mirror of
https://github.com/boostorg/website.git
synced 2026-01-22 17:52:30 +00:00
294 lines
14 KiB
HTML
294 lines
14 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
|
<head>
|
|
<title>Error and Exception Handling</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<link rel="icon" href="/favicon.ico" type="image/ico" />
|
|
<link rel="stylesheet" type="text/css" href=
|
|
"/style-v2/section-community.css" />
|
|
<!--[if IE 7]> <style type="text/css"> body { behavior: url(/style-v2/csshover3.htc); } </style> <![endif]-->
|
|
</head><!--
|
|
Note: Editing website content is documented at:
|
|
https://www.boost.org/development/website_updating.html
|
|
-->
|
|
|
|
<body>
|
|
<div id="heading">
|
|
<!--#include virtual="/common/heading.html" -->
|
|
</div>
|
|
|
|
<div id="body">
|
|
<div id="body-inner">
|
|
<div id="content">
|
|
<div class="section" id="intro">
|
|
<div class="section-0">
|
|
<div class="section-title">
|
|
<h1>Error and Exception Handling</h1>
|
|
</div>
|
|
|
|
<div class="section-body">
|
|
<h2>References</h2>
|
|
|
|
<p>The following paper is a good introduction to some of the
|
|
issues of writing robust generic components:</p>
|
|
|
|
<blockquote>
|
|
<p><a href="/community/exception_safety.html">D. Abrahams:
|
|
``Exception Safety in Generic Components''</a>, originally
|
|
published in <a href=
|
|
"https://doi.org/10.1007/3-540-39953-4">
|
|
M. Jazayeri, R. Loos, D. Musser (eds.): Generic Programming,
|
|
Proc. of a Dagstuhl Seminar, Lecture Notes on Computer
|
|
Science. Volume. 1766</a></p>
|
|
</blockquote>
|
|
|
|
<h2>Guidelines</h2>
|
|
|
|
<h3>When should I use exceptions?</h3>
|
|
|
|
<p>The simple answer is: ``whenever the semantic and
|
|
performance 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 ring to it but is usually a mistake. The
|
|
problem is that one person's ``exceptional'' is another's
|
|
``expected'': when you 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.</p>
|
|
|
|
<p>A more appropriate question to ask is: ``do we want stack
|
|
unwinding here?'' Because actually handling an exception is
|
|
likely to be significantly slower than executing mainline code,
|
|
you should also ask: ``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 canceled 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. The guideline mentioned above
|
|
has a grain of truth in it: in time-critical code, throwing an
|
|
exception should <em>be</em> the exception, not the rule.</p>
|
|
|
|
<h3>How should I design my exception classes?</h3>
|
|
|
|
<ol>
|
|
<li><strong>Derive your exception class from
|
|
<code>std::exception</code></strong>. 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>
|
|
<strong>Use <i>virtual</i> inheritance.</strong> This
|
|
insight is due to Andrew Koenig. Using virtual inheritance
|
|
from your exception's base class(es) prevents ambiguity
|
|
problems at the catch-site in case someone throws an
|
|
exception derived from multiple bases which have a base
|
|
class in common:
|
|
<pre>
|
|
#include <iostream>
|
|
struct my_exc1 : std::exception { char const* what() const throw(); };
|
|
struct my_exc2 : std::exception { char const* what() const throw(); };
|
|
struct your_exc3 : my_exc1, my_exc2 {};
|
|
|
|
int main()
|
|
{
|
|
try { throw your_exc3(); }
|
|
catch(std::exception const& e) {}
|
|
catch(...) { std::cout << "whoops!" << std::endl; }
|
|
}
|
|
</pre>The program above prints <code>"whoops"</code> because the C++ runtime
|
|
can't resolve which <code>exception</code> instance to match in the first
|
|
catch clause.
|
|
</li>
|
|
|
|
<li>
|
|
<strong><i>Don't</i> embed a std::string object</strong> 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 <i>throw-expression</i> that includes construction
|
|
such as:
|
|
<pre>
|
|
throw some_exception();
|
|
</pre>
|
|
|
|
<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><strong>Format the <code>what()</code> message on
|
|
demand</strong>, 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><strong>Don't worry <i>too</i> much about the
|
|
<code>what()</code> message</strong>. 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=
|
|
"/users/people/peter_dimov.html">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 message formatters. Now if only we could get
|
|
standardized <code>what()</code> strings for exceptions
|
|
thrown by the standard library...</li>
|
|
|
|
<li><strong>Expose relevant information about the cause of
|
|
the error</strong> in your exception class' public interface.
|
|
A fixation on the <code>what()</code> message is likely to
|
|
mean that you have neglected to expose information someone might
|
|
need, in order to make it 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
|
|
<i>as numbers</i> 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 <code>what()</code> string, you will make life
|
|
very difficult for programmers who need to do something more
|
|
(e.g. subtraction) with them than dumb output.</li>
|
|
|
|
<li><strong>Make your exception class immune to
|
|
double-destruction</strong> 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>
|
|
|
|
<p>As a developer, if I have violated a precondition of a
|
|
library I'm 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 <code>assert()</code> or something like
|
|
it.</p>
|
|
|
|
<p>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 that
|
|
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><strong>Note for Windows developers</strong>: unfortunately,
|
|
the native exception-handling used by most Windows compilers
|
|
actually throws an exception when you use
|
|
<code>assert()</code>. 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 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>
|
|
<pre>
|
|
extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
|
|
{
|
|
throw;
|
|
}
|
|
extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)
|
|
= _set_se_translator(straight_to_debugger);
|
|
</pre>
|
|
|
|
<p>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.</p>
|
|
|
|
<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 to 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.
|
|
|
|
<p>I reluctantly concede this point to Hillel Y. Sims, after
|
|
many long debates in the newsgroups: until all OSes are
|
|
"fixed", if every exception were derived from
|
|
<code>std::exception</code> and everyone substituted
|
|
<code>catch(std::exception&)</code> for
|
|
<code>catch(...)</code>, the world would be a better place.</p>
|
|
|
|
<p>Sometimes, <code>catch(...)</code>, 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 <i>must</i> stop
|
|
unwinding it's probably still your best bet. One obvious place
|
|
where this occurs is at language boundaries.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="sidebar">
|
|
<!--#include virtual="/common/sidebar-common.html" -->
|
|
<!--#include virtual="/common/sidebar-community.html" -->
|
|
</div>
|
|
|
|
<div class="clear"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="footer">
|
|
<div id="footer-left">
|
|
<div id="revised">
|
|
<p>Revised $Date$</p>
|
|
</div>
|
|
|
|
<div id="copyright">
|
|
<p>Copyright David Abrahams 2001-2003.</p>
|
|
</div><!--#include virtual="/common/footer-license.html" -->
|
|
</div>
|
|
|
|
<div id="footer-right">
|
|
<!--#include virtual="/common/footer-banners.html" -->
|
|
</div>
|
|
|
|
<div class="clear"></div>
|
|
</div>
|
|
</body>
|
|
</html>
|