|
Boost : |
From: williamkempf_at_[hidden]
Date: 2001-04-11 17:25:43
--- In boost_at_y..., Jesse Jones <jesjones_at_h...> wrote:
> At 1:41 PM +0000 4/11/01, williamkempf_at_h... wrote:
> >--- In boost_at_y..., Jesse Jones <jesjones_at_h...> wrote:
> > > > > 6) Trying to invoke an empty function seems like a
precondition
> >> >> violation to me. Asserting instead of throwing seems
preferable.
> >> >
> >> >I disagree because using an assertion means that the check
might
> >be turned
> >> >off. If that happens, any_function will cause a segmentation
> >violation. At
> >> >least throwing an exception gives some form of recovery.
> >>
> >> Would you also throw if someone passed a nil char* into
> >std::string's
> >> ctor? Indexed past the end of a std::array? Passed bogus
iterators
> >> into std::find? Personally I don't think any of these should
throw:
> >> they should assert whenever possible and follow the normal code
> >path
> >> thereafter. This is *exactly* what asserts are for.
> >
> >Indexing past the end of std::array does throw, at least when you
use
> >at() instead of []. This kind of throws your whole argument here
> >out.
>
> Not really. In one place out of the thousands(?) of preconditions
in
> the standard they provided an alternate API that throws. All this
> means is that committee was unwilling to use exceptions for
> precondition violations except in one special case.
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.
> >I'm really learning to hate exceptions. _NO ONE_ agrees on
> >when they should be used. Even people who think they have their
own
> >set of rules for when to use them seem to violate the rules
> >themselves from what I've seen.
>
> Yeah, but it's important to talk about this stuff. Design by
> Contract, for example, has a lot of merit, but vendors have as a
rule
> done a terrible job providing debugging support in their libraries.
> I'd like to think that boost could do better.
I'd agree with this... but read on.
> >As for the argument that asserts should be used instead... an
assert
> >is a C concept that existed before exceptions. In fact, other
> >languages throw exceptions on failed assertions to further cloud
this
> >argument. Saying that this is exactly what assertions are for does
> >not help to argue your case, or to help people like me figure out
> >when to use what kind of error handling.
>
> The only language that I know about that handles this stuff well is
> Eiffel. There you have language support for preconditions,
> postconditions, and invariants. By default failures throw, but you
> can turn off all the checks in release if you desire. This is
> *exactly* what I want: rigorous checking of preconditions and
> postconditions coupled with a global policy to control the behavior
> of failures. Of course we're not there yet, but it would be great
if
> people would begin to think in this way when they implement classes.
Eiffel has a minimal "global policy for failures". Basically, you
can turn assertions on or off (with varying levels according to
whether they're preconditions, postconditions or invariants). You
can't redefine what occurs when assertions fail to, for instance,
halt the program immediately or to log the error to a file.
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.
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.
3) Violation of pre/post-conditions and invariants.
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.
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk