Re: Exceptions, Go to Hell!
On 8=E6=9C=8827=E6=97=A5, =E4=B8=8B=E5=8D=888=E6=99=8201=E5=88=86, Goran Pu=
sic <gor...@cse-semaphore.com> wrote:
On Aug 27, 9:54 am, w...@seed.net.tw wrote:
std::vector<T> arr=initialize();
size_t i;
try {
for(i=0; i<arr.size()+1; ++i) {
if(arr.at(i)==T()) break;
}}
catch(const std::out_of_range& e) {
assert(i>=arr.size()); // Can I really assure this asse=
rtion?}
I am not sure why I was quoted for this snippet, nor what is the
purpose of it all, but here goes...
Because I read your sorting 2, triggered my obsession that I wanted
to notify you that the caught object (especially if they are reused)
can mean differently, not as most people thought. Throw type for
dedicated purpose is fine, though. Slightly modified example to
clarify:
std::vector<T> arr(100);
size_t i=0;
try { arr.at(i); }
catch(const std::out_of_range&) {
assert(i>=arr.size()); // Time bomb! Can I really assure this
// assertion?
}
This code most certainly has a bug. It makes no sense whatsoever to
ever try to call at(v.size()).
Exceptions are __not__ means of handling bugs. A "catch" like the one
you made is an attempt at handling an exception, therefore, at
handling a bug. Therefore your catch is misplaced.
Exceptions __can__ be used to __report__ bugs, but they are often
suboptimal for that, too; if possible in the given runtime
environment, a crash and a dump is better, because that allows you to
see the exact place where problem happened, which, in case of a bug,
is important. If, however, you do want to use them to report bugs, you
should let them unwind the stack up to the end and terminate. You
__may__ do ^^^ on the way up the stack, though.
Catching the exception above, that is caused by a bug, is a __bad__
idea. Bugs should be fixed, not "handled". Unless code inside catch
can somehow change the "i<arr.size()+1" to something correct, it makes
no sense whatsoever to catch anything, except if the purpose is to
mask the bug and do something wrong anyway.
As for invalid_argument, I guess you wanted to hint at the possibility
that operator== could throw that. Well, invalid_argument, because
invalid_argument is, just like out_of_range, a logic_error, that is, a
bug. Same logic applies.
If, by any chance, you did something like:
// ^^^
catch(const logic_error& e)
{
string more("We have a bug. We caught it in " + string(__FILE__) +
", line " + string(__LINE__) + "error text was: "
+ string(e.what());
throw logic_error(more);
}
I remember I read from a book that C++ does not guarantee the proper
handling if the size of thrown object is larger than the standard
exception type. I am appropriate if anyone can point out a reference.
The above code is potential for bad_alloc.
, that is, if you were in 2) of my exception classification ;-), your
catching would have some sense. The way it is now, everything you
wrote is one huge bug to me.
General guideline for throw site: "stack unwinding to exit".
I don't know what you mean by this, but I know that throw site can't
decide what will happen with the thrown exception. Next function can
catch it, so what gives?
Goran.
Maybe just different terms for the same thing, not necessarily
against your opinion.