Jerry said:
A contrast violation means there is something wrong with the code (i.e.
a bug) that has been found and noted, and needs to be fixed.
For the record, I wasn't really considering the context of the quoted
message, just exception handling in general.
Now, if you were to use exception handling, and base your exceptions off
the standard exceptions, a contract violation would be considered a
std::logic_error. There are other types of exceptions that you might use
that would not be the result of a contract violation.
But looking at just the contract violation case, obviously it's a bug
that should be fixed. But at least some bugs always make it into the
final product. Terminating the program when a problem is found is not a
very useful behavior from the perspective of the user of the
application. In fact, I don't think most users would be very happy with
that.
In this case, aborting is a LONG ways from being the worst case. Quite
the contrary: the worst case is that the problem is allowed to continue
unnoticed for some arbitrary period of time
Yes, I agree that this is bad. But it only happens if you explicitly
ignore the exception.
-- almost inevitably, the
longer a bug persists, the more difficult and expensive it is to fix.
Therefore, when you DO find what you're sure is a bug in some code, the
best case is to ensure that it fails as quickly, dependably and
spectacularly as possible, so it will be fixed as soon as possible
instead of being allowed to persist.
This is not true from the user's perspective, though.
The problem with throwing an exception in a case like this is that it's
all too easy (and common) for somebody to do something like this:
int main(int argc, char **argv) {
do {
try {
return real_main(argc, char **argv);
}
catch(...) {
std::cerr<<"Some problem -- retrying\n";
}
} while(1);
return 0; // never really executes
}
In fact, almost any instance of "catch(...)" can cover up an almost
arbitrary collection of problems that the library designer is TRYING to
make sure get noticed.
Yes, I definitely agree that this is a problem. But one way to look at
it is that it's not really *your* problem. If you threw the exception,
you've done your part. If the caller ignores it, then they screwed up.
But this doesn't make any difference in many cases. If the program
breaks for the customer, you'll still be in trouble.
So I see the point, but I don't think aborting is an ideal solution, in
particular once the program is in the customer's hands. An exception
could be an ideal solution, if it's not ignored. As far as I know,
there's no way to be sure of this.
A few ideas come to mind, but none is anywhere near perfect. You could
abort or throw depending on a build setting, for example. But if you
test with abort and ship with throw then you don't even know if the
catching code is in place or doing anything sensible. You'd have to test
with throw, and it could be covered up.
You could try to make an un-ignorable exception, maybe. Suppose your
exception object includes a 'handled' flag. On construction, this flag
is false. The catcher must set it to true. On destruction, if the flag
does not indicate that the exception was handled, the destructor aborts
the program. The problem is that it can still be ignored, it just takes
a little more effort (catch, set the flag, do nothing else).
-Kevin