Boost logo

Boost :

From: David Abrahams (abrahams_at_[hidden])
Date: 2001-03-19 14:55:53


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

>
> This is the part that's still tricky to me, at least in this
> particular case. The violations are user violations (almost all
> precondition violations are user violations by definition). Here you
> say to call it undefined behavior and to do what ever I like, but
> earlier it was stated that all undefined behaviors should be
> asserted, which makes sense at a high level. The problem is, asserts
> terminate the app and are detectable only when "turned on". The
> original thread that started this was the checks on misuse of locks
> (which may in the future be extended to deadlock detection above and
> beyond the normal checks). This condition can often arise from race
> situations in threaded programming so checking only when the
> assertions are turned on can result in undefined behavior that's
> never caught during debugging. Further, it's a situation in which
> many programs can easily and safely recover from the error. So both
> qualities of the assert _seem_ detrimental to use here.

Why do we throw an exception from memory allocation routines when memory
can't be allocated instead of saying making it a precondition that enough
memory is available? In some sense, it all comes down to practicality: it is
difficult or impossible for the user to check that enough memory will be
available to perform a particular allocation (yes, there are other reasons,
too).

Nearly all of the logic errors I have to check for can be expected to be
caught during routine testing, and for those I use good old assert. Very
rarely there are conditions which I expect to be true but cannot convince
myself will be true deterministically under every possible circumstance. For
these conditions, an exception may be appropriate. The conditions being
checked for here may fall into the same category.

An aside: if we are going to rigorously check our clients' usage of our API
for errors, we ought to distinguish those checks from the (IMO exceedingly
useful) assertions we use to sanity-check our own code. It may be
appropriate to compile away the internal checks, while turning the API abuse
checks into exceptions.

Another aside: Please note that nothrow operations are a cornerstone of
exception-safe code. One great value of assertions is that they can be used
liberally without fear of affecting the shipping program's efficiency or
semantics (assuming side-effects are avoided). If we start using assertions
which may sometimes throw, we will have to account for the fact that a
sequence of operations that might have been nothrow suddenly loses that
property. The program is now expected to be able to function correctly (or
at least recover) when arbitrary operations have been interrupted by
exceptions. I don't like this complication, and would prefer to very
carefully distinguish a throw from an assert().

-Dave


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