    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Exception Discussion</title>
        <link>https://members.accu.org/index.php/articles/571</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Project Management + Overload Journal #29 - Dec 1998</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c66/">Management</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c199/">29</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c66-199/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c66+199/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Exception Discussion</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 27 December 1999 17:23:23 +00:00 or Mon, 27 December 1999 17:23:23 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="section" lang="en">
<div class="titlepage">
<h2><a name="d0e21" id="d0e21"></a></h2>
</div>
<div class="variablelist">
<dl>
<dt><span class="term">The Harpist:</span></dt>
<dd>
<p>Below is a letter from Ken Hagen that I have annotated with a
few comments as I read it. I hope that you will read plenty of
smileys into my notes as what he says is useful, and he has much in
common with many other programmers. I think the move to writing
code in an exception handling environment is even bigger than the
move to OO. I think that the Standards Committees have let us down
by lacking the courage to support exceptions with a good exception
specification (ES) scheme.</p>
<p>I think that many writers let us down with na&iuml;ve exception
handling code. I am disappointed to see how many gurus take such a
negative attitude to the concept of ES and static analysis. We need
static analysers and we need to write code that can benefit from
them. It is a little chicken and egg problem.</p>
</dd>
<dt><span class="term">Ken Hagen:</span></dt>
<dd>
<p>I was interested to follow The Harpist and Detlef Vollmann as
they exchanged views on exception specifications. However, my own
impression is that too many authors are now advocating widespread
exception usage where it is not appropriate. As I understand it,
exceptions are supposed to be a superior alternative to return
codes for two reasons.</p>
<p>It is easy to separate the point of detection from the point of
handling. So easy, in fact, that exceptions can travel huge
distances up the stack with little or no effort on the part of the
programmer.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>The language semantics for stack unwinding clean up
automatically, eliminating one of the larger costs of propagating
errors in a traditional scheme. Therefore, a single catch point can
service many points of failure.</p>
<p>While I agree that a single catch could service many points of
failure, generally the failure should be handled at the earliest
opportunity. What I am seeking is a way to make this likely by
using ES to limit the normal propagation. Static checking of ES
should allow early detection of late handling.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>I propose to argue that both of these are wrong in the majority
of situations, and that... The separation of detection from
handling leaves different levels of the program coupled. This is
poor practice, and anything that encourages it is suspect.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>Au contraire, the idea is to reduce coupling. When a disk is
full, my output routines can detect the problem but I have
absolutely no idea as to what the user (client programmer for my
library) wants to do about that. Exceptions provide as much
decoupling as is possible. Agreed that it does not decouple the
two, but the process of writing a file is inherently coupled to the
output stream doing the job. What should not happen is that the
process of writing a stream need know why it is doing it.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>The automatic unwinding is useless in the vast majority of
cases, where side effects (not resources) are what we want to clean
up. Line by line clean-up is usually needed, making a single catch
point impossible.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>Excuse me, you are the one specifying a single catch point. What
I expect is that resources are released between the point of
detection (throw point) and the appropriate catch point. Imagine
that my program has acquired the use of a serial port. Imagine also
that it is a long running program that is robust and
fault-tolerant. In other words the program may run for days and
knows how to recover from problems. How do you propose to ensure
that the serial port is released if some exception is raised after
acquisition of the serial port and is caught at a stage when the
serial port should have been released? Note that to the best of my
knowledge, Java cannot handle this problem because it has no way to
force the running of <tt class="methodname">finalize</tt>
methods</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>I will then argue that making functions safe for exceptions to
propagate through them is much harder than writing no-throw
versions, and so I conclude that:</p>
<p>Exceptions should be avoided wherever possible and <tt class=
"methodname">throw()</tt> appended to every function prototype.
Library interfaces should never use them.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>Oh, and how exactly do you propose that the string ctor report
that it has been unable to acquire sufficient memory to complete
its task? Of course the programmer needs to catch that problem as
soon as it occurs but there is absolutely nothing that the library
implementor can do except shout loudly (i.e. <tt class=
"literal">throw std::bad_alloc()</tt></p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Separation first. It is best to handle errors as close to the
point of failure as possible. (People can disagree over how close
that is, mind you.) Exceptions don't prevent this, but I think most
of us would feel something was wrong if <tt class=
"literal">try</tt>/<tt class="literal">catch</tt> blocks were as
common as if/else in a section of code, and it is easy to write a
few centralised <tt class="literal">try</tt>/<tt class=
"literal">catch</tt> blocks and throw exceptions over long
distances. The result is that exceptions favour separation of
detection from handling, and centralising all handling in a few
places. There are two problems with this</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>That is a matter of education. How many C programmers ever test
the return value of <tt class="function">malloc()</tt>. Some do and
some do sometimes but most do not. Putting ES in your code
highlights lazy programmers who simply cannot be bothered to catch
problems early because their exception specifications will grow out
of control.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Some or all of the context of the problem may be lost as part of
the stack unwinding process. Even the location of the error may be
lost if functions make heavy use of common exception classes.</p>
<p>The remaining context is only preserved if either the exception
carries a lot of information which the handler understands, or the
handler has enough knowledge of the implementation to deduce the
throw point and its context.</p>
<p>Considering the first of these, taking appropriate action (as
distinct from simply printing &quot;Operation failed&quot; and running away)
becomes proportionately more difficult as the catch point retreats
from the throw point. It is easy to attach an error message to
almost any exception, but most errors are not best handled by
telling the user about the problem. Usually, we need an alternative
program flow. Perhaps we try a different algorithm, slower but
cheaper or safer. Perhaps we try a different operation, as when we
fail to find an important file and fall back on a &quot;last known
good&quot;, or built-in defaults.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>I think you miss the point. There are two possible places for
catch clauses, immediately after the suspect operation. In other
words there is a visible throw in the try block. This simply
bundles problems in one place in your block of code. The second
sane place is in the code that called the function that threw the
exception. Sometimes a greater distance is acceptable but if we use
ES those case become visible to all concerned. It is the omission
of an ES that causes the problem.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Let us overcome this first problem by filling our exception
object with a lot of descriptive data, or by simply knowing enough
about the implementation of the functions we're calling that we can
deduce what happened. This is a coupling between the detection and
the handling; one has to know about the other. Over short
distances, as might commonly occur if we were passing return codes
around, this probably isn't a problem. Over longer distances it is
the sort of coupling between two levels of abstraction that we like
to avoid.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>What about Francis' favourite <tt class=
"exceptionname">EndOfProgram</tt> exception? How else would you
propose that we terminate a program correctly in an environment
where clean-up is needed?</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>I conclude that most exceptions are best confined to small areas
of code where all the functions are designed and implemented
together. That way, the context is pretty obvious and coupling
isn't much of a problem anyway. This restriction precisely fits the
areas of the language where exceptions are absolutely necessary:
constructors, destructors and overloaded operators that cannot
return an error code. If these throw an exception, we should catch
it immediately.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>Hang about, what is this belief in error codes? Every bit of my
experience says these are a menace because programmers ignore them
with the result that programs can go completely wild. However I
entirely agree with you on the subject of writing code that handles
exceptions as soon as possible. Doing anything else is silly.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Unwinding next. There is an idiom by the name of &quot;resource
acquisition is initialisation&quot;. The idea is that the constructor
grabs the resource, and the destructor releases it. Its first
selling point is that since destructors are always called, even
when unwinding, we never leak resources. The second is that since
destructors are always called in reverse order of construction, the
resource releasing generally occurs in precisely the right order.
The natural unwinding of C++ is precisely what we need, so we don't
have to add anything.</p>
<p>Sadly, if the destructor experiences an error (say, in
committing changes to a file) we are stuffed. (It cannot throw an
exception, because exceptions during unwinding are fatal program
errors.) Also, resource acquisition is the only case where the
natural unwinding of C++ is what we need. A much more common kind
of &quot;unwinding&quot; is carefully unpicking all the side effects that we
accumulated before we ran into trouble. Most of the interesting
behaviour of a program lies in its side effects and it is extremely
common to have a sequence of operations directed to some larger
goal.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>What you are talking about is commit or rollback and exceptions
actually help with that. What a destructor must do is catch any
exceptions and do what it can with them. What it must not (in
general) do is propagate any exception. There are a few rare cases
where it might be acceptable to allow a destructor to throw an
exception if no other is being processed because something could be
done to fix the problem before making another attempt to destroy
the object. However this case is so rare that I have yet to see an
example of it in live code.</p>
<pre class="programlisting">
CreateNewRecord()
CopyHeaderOver()
for (int record=0; record&lt;10; ++record)
  CopyBody(record);
SubmitNewRecord()
for (int record=0; record&lt;10; ++record)
  DeleteRecord(record);
</pre></dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Each of these operations may have some side effect, and will
require some sort of &quot;Undo&quot; if an error occurs. Obviously we only
want to undo the things we've done, so we'll be watching for
success or failure at each step. Such fine-grain error detection
can be based on either <tt class="literal">try</tt>/<tt class=
"literal">catch</tt> or <tt class="literal">if</tt>/<tt class=
"literal">else</tt> constructions, but it will be line-by-line and
heavily nested in either case. It doesn't matter how you catch the
error.</p>
<p>Except that it does. Consider the following example from &quot;Guru
of the Week&quot; (<a href="http://www.cntc.com/resources/gotw020.html"
target="_top">http://www.cntc.com/resources/gotw020.html</a>).</p>
<pre class="programlisting">
String EvaluateSalaryAndReturnName
  ( Employee e )
{
  if( e.Title() == &quot;CEO&quot; 
  || e.Salary() &gt; 100000 ) 
  {
    cout &lt;&lt; e.First() &lt;&lt; &quot; &quot; &lt;&lt; e.Last() 
        &lt;&lt; &quot; is overpaid&quot; &lt;&lt; endl;
 }
  return e.First() + &quot; &quot; + e.Last();
}
</pre>
<p>There are 23 paths through this code. If we can specify
&quot;<tt class="function">throw()</tt>&quot; on all our functions, then we
can ignore 20 of them and just worry about 3. (The &quot;<tt class=
"literal">if</tt>&quot; test can go either way, and it contains a
logical or so the second expression may never be evaluated.) Guess
which version is easier to verify and maintain! The real problem is
that most of these paths are implicit. Implicit actions, such as
automatically invoking a constructor when we declare a variable,
are a Good Thing when they do what we want. Here they are
threatening to bypass the declared flow of control. This isn't so
good.</p>
<p>Most of the operations in this example either won't throw or
have no side effects worth undoing, or both. However, if they did,
and we attempted full backtracking, we would need line by line
testing and would quickly arrive at a 40 line function. For robust
software, we ought to write that 40 liner. The ease with which we
can reduce it to 4 lines and a bucket of exceptions should not
tempt us into doing so. The longer version is clearer, and sooner
or later clarity will translate into quality. Long term side
effects, not short term resource usage, is the point of most
programs, so the promise of &quot;automatic housekeeping&quot; just doesn't
pan out.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>No, that is not the way to do commit or rollback. I think that
like many of us you have yet to develop a style of C++ programming
that works well with exceptions. You may need to rollback manually
but that is itself dangerous. What happens if something goes wrong
during the rollback?</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>My conclusion from this is that exceptions are bad psychology
(encouraging people to give up early and leave the problem for the
caller to deal with) and bad design (because return codes only
couple to the immediate caller, but exceptions couple over much
larger distances). Furthermore, because error codes are explicit,
they are easier to read and omissions are easier to detect. So when
would I ever use an exception?</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>If this is true, error codes are even worse psychology.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Only when I have to. Constructors, destructors and most
overloaded operators cannot return errors in any normal sense. I
normally keep &quot;risky&quot; operations out of these kinds of function,
but sometimes it is a better compromise to throw and catch
exceptions. Even in these cases, I would prefer to catch the
exception locally and either handle it or return a conventional
error code. Similarly I might decide that a small cluster of
(usually private) functions are best expressed by blindly hoping
for the best and catching all errors in a single catch in the
caller. This happens when the number of possible failures (or the
call stack depth) is large and the number of side effects to be
unpicked is small. Again, I would still want to catch the exception
at the closest reasonable level and turn it into an error code.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>You really have more faith in error codes than I do. Even worse,
the handling of error codes cannot be statically checked by any
known or imaginable analysis tool.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p>Either way, I remain unconvinced that a major public interface
(such as for a 3rd party library) should ever threaten to throw an
exception. A return code is cheaper at run-time, more portable to
non C++ clients or special C++ environments (such as Microsoft's
COM), and does not require every caller to be exception aware.
Which brings me to the standard language and library, which have 4
exceptions each. Fortunately, there are realistic alternatives to
some of them.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>I ask again; exactly how do you propose to manage resource
failures? The writer of an <tt class="methodname">operator &gt;&gt;
()</tt> for a class has absolutely no chance of knowing what you
want to do if the operation fails. Aborting a program because an
<tt class="classname">istream</tt> has failed seems massively over
the top to me, but how else do you propose to ensure that the
program does not ignore this problem. An error return (even if
possible - you cannot have these for operators) does not work. Even
worse, in multi-threaded code error flags (essentially static in
many cases) are an unmitigated disaster.</p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p><tt class="literal">dynamic_cast</tt> throws <tt class=
"exceptionname">bad_cast</tt>, but only if you use a reference.
Casting a reference when you cannot prove the cast will succeed is
a design error on a par with dereferencing a pointer which may be
NULL.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>Really? I know many people who would disagree. Though I prefer
using a pointer and checking for a null pointer, that is hardly
different from using a catch. It really depends on context. The
design error is neither checking for null nor catching <tt class=
"exceptionname">bad_cast()</tt></p>
</dd>
<dt><span class="term">KH:</span></dt>
<dd>
<p><tt class="literal">typeid</tt> throws <tt class=
"exceptionname">bad_typeid</tt> if you give it a NULL pointer. I
have no sympathy here either.</p>
<p><tt class="exceptionname">bad_exception</tt> is available to
automatically map exceptions, which are not in the function's
specification. You'd be better off specifying things properly at
compile time.</p>
<p><tt class="exceptionname">out_of_range</tt> causes me the most
amusement. It seems that the new-fangled &quot;safe&quot; containers are so
difficult to use that we can't be expected to know whether the
index is within range until we try it. Er, why not check the size
first, like we've been doing for the past 4 decades?</p>
<p>Lastly, we have <tt class=
"exceptionname">ios_base::failure</tt>. In this case, <tt class=
"exceptionname">ios_base::exceptions</tt> can be used to control
the behaviour. Exceptions might actually be &quot;in their element&quot; for
some forms of I/O. I can imagine reading configuration information
which is in plain text format for flexibility, but which
nevertheless should be syntactically perfect because it is part of
the program rather than the user input. If we take the view that
&quot;all errors are fatal&quot; for this data, then a single catch covering
a multitude of input statements would be the smart way to handle
it. For user input, I might still use an exception, but it would be
one of my own with enough additional context information to
indicate precisely where and what the error was.</p>
<p>Missing from this list are two other exceptions throw by
<tt class="classname">bitset</tt>s. <tt class=
"exceptionname">invalid_argument</tt> is thrown when a <tt class=
"classname">bitset</tt> is constructed from a string, which doesn't
contain just ones and zeroes. Obviously it would take as long to
check the argument as it does to construct the bitset, so at first
I had some sympathy here. Then I thought why not use a member
function that does return an error, rather than a cute constructor
that can't. Then I noticed, there is no such member. Failing to
provide this assignment is surely an omission. Secondly, the
conversion from <tt class="classname">bitset</tt> to integer
(<tt class="type">unsigned long</tt>) runs the risk of the
<tt class="exceptionname">overflow_error</tt> exception. Since the
maximum size of the <tt class="classname">bitset</tt> is part of
its type, this strikes me as another problem that could be proven
at compile time or checked at run-time. Sadly, there seems to be no
easy way to determine the most significant non-zero bit, or indeed
any group of bits beyond the first <tt class=
"methodname">numeric_limits&lt;unsigned long&gt;::digits</tt>. This
is surely another omission. I'm not impressed with this class. If I
really needed bitsets longer than my longest integral type, I'd
write my own.</p>
<p>Harder to deal with is operator new and <tt class=
"exceptionname">bad_alloc</tt>. I would suggest you use the nothrow
variant, and I expect you could create STL <tt class=
"classname">allocator</tt>s that use this strategy, but I also
suspect that most implementations of the STL assume their
allocations succeed.</p>
<p>It is a real shame that exception specifications are not
enforced. I'd have far fewer qualms about using exceptions if they
were as strongly typed as return values. At least then I would know
what I had to worry about. The language urgently needs a way of
writing templates that &quot;pass-through&quot; the exception specifications
of their arguments. A way of modifying that list would be nice too,
but I fear the latter is the enemy of the former, and we will get
neither until someone has worked.</p>
</dd>
<dt><span class="term">TH:</span></dt>
<dd>
<p>It wasn't until I got to the last few of paragraphs that I
finally realised that at heart you are a C programmer. For a long
time I thought that the decision to have new throw <tt class=
"exceptionname">bad_alloc</tt> was terrible because it broke so
much existing code. More recently I have come to realise that it
was that decision that powers the STL. Yes exceptions make heavy
demands on our coding style. Coding with them requires an entirely
different approach to coding without them. Few programmers and even
fewer authors realise this.</p>
<p>There are clearly several places where there are no sensible
options to using exceptions. For example both constructors and
user-defined operators provide no alternatives. Surely the right
answer is to teach programmers how to write good code in the
context of exceptions. If only the rules of the language provided
better support that should include using exception specifications
and catching problems as soon as reasonable but no sooner. If
programmers learnt to do the latter and the language gave good
support for the former many exception specifiers would reduce to
<tt class="function">throw()</tt>.</p>
<p>C++ is nothing like C but until programmers realise that we will
continue to get C idioms argued as being the correct solution to
C++ coding problems.</p>
<p>Having said that, thanks for the viewpoint. Probably more people
agree with you than agree with me.</p>
</dd>
</dl>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
