Boost logo

Boost :

From: David Abrahams (abrahams_at_[hidden])
Date: 2001-04-11 18:03:41


----- Original Message -----
From: <williamkempf_at_[hidden]>

> The problem I have is why is there "one special case"? It's
> decisions like this that make it impossible to know when to use
> exceptions and when not to.

IMO, it's because other languages (with other error models) have
bounds-checked arrays, and users of other languages have asked for years,
"what about bounds checking? Pascal has bounds checking!" Peer pressure is
an ugly thing ;-)

> More importantly, since these *ARE* exceptions you can catch them and
> continue program execution. C/C++ asserts do not behave this way at
> all. So you aren't really in favor of assertions here, but rather in
> a configurable mechanism that will throw an exception when the policy
> is turned on. Dave, on the other hand, doesn't like exceptions
> because they unwind the stack making debugging difficult.

Anyone who thinks I don't like exceptions hasn't been paying attention!

I don't like exceptions as the primary mechanism for reporting /detected
program bugs/. If you want to assert (or something similar) first, and then
throw an exception later, it's OK with me.

> It seems to me that there are 3 types of errors that one needs to
> decide how to handle:
>
> 1) Expected errors, such as a search that fails to find anything.
> 2) Unexpected errors, such as trying to allocate memory when there's
> none left.

IMO "expected/unexpected" isn't a very good distinction (see
http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/~checkout~/boost/more/error_ha
ndling.html?rev=1.1&content-type=text/html&cvsroot=boost).

I would not normally call #1 an error. I think doing so muddles the issues
and makes it harder to understand when to use exceptions. When a search does
not find the item sought, the search completes normally. "Not found" is
simply one possible result of a search (e.g. std::find returns the end
iterator). I would not normally use an exception for this. Of course there
are operations when you want to make it a precondition that an item can be
found, but those fall into the category of precondition violations (see
later)

If we didn't "expect" to run out of memory (#2), there would be no point in
throwing, catching, or even defining a bad_alloc exception. These errors
fall into the category of resource allocation failures. The category is
really "indirect preconditions that there is no practical way for the caller
to check", but that's hard to write, and nearly everything in the general
category is actually a resource allocation failure anyway. For these,
exceptions are usually a good choice.

> 3) Violation of pre/post-conditions and invariants.

I don't think you should glom all of these into one category.

IMO, invariants and postconditions should be asserted. They are under your
control. If your invariants are broken it's unlikely that the program can do
any useful recovery anyway.

In some cases it may make sense to throw exceptions when (argument)
preconditions are violated. For example, if you are writing a Java or Python
extension, it is expected not to crash under any circumstances. It is
consistent with the language to respond to caller abuse with an exception.
It is equally consistent with the goals of some library vendors to check all
preconditions carefully and avoid crashing. As I write in the page above,
doing this carefully and completely can be very expensive. It often involves
redundant tracking of the address of every object exposed to the library
clients.

> Most people will agree that (1) warrants an error return code while
> (2) warrants an exception (though it's often hard to tell the
> difference between (2) and (3) for some errors). It's (3) that's got
> everyone up in arms. Most people would agree you need to be able to
> shut these sorts of checks off for release builds, though it seems
> valid to leave them on even for release builds under certain
> circumstances (and those may not be on an app wide case, making this
> harder to deal with). However, when on should they halt the program
> (assert) or throw an exception?
>
> If Boost really wants to do the "best thing" here I think we need
> written guidelines and a BOOST_ASSERT(?) for case (3). With out both
> of these every time this argument comes up I'd expect us to rehash
> everything again and again with no real resolution to the topic.

That's the reason for the page referenced above (in CVS at
http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/boost/more/error_handling.html
?cvsroot=boost). It just hasn't made it into a release yet.

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk