From: Goran on
On Jan 8, 4:37 pm, Peter Schneider <peter.m.schnei...(a)gmx.de> wrote:
> On 7 Jan., 15:32, Goran <goran.pu...(a)gmail.com> wrote:
>
> > In particular, though, I do think that CInvalidArgException is bad,
> > because it's usually a sign of a bug in the program. But exceptions
> > are strictly __NOT__ a mean to treat bugs, not in the slightest. On
> > top of that, there's this unlucky change in behavior between MFC
> > versions (bad index would essentially crash before, but will throw
> > now).
>
> If I remember correctly, Java uses exceptions for both "normal" error
> handling and for reporting programming errors including assertions.
> And that seemed to work pretty well and has the advantage that there
> is only one mechanism used.
>
> Contrast this to C++ and in particular to C++ on WIN32 where there are
> many different handlers for all kinds of unexpected errors (e.g.
> _set_abort_behavior, _set_purecall_handler,
> set_terminate,set_unexpected, SetUnhandledExceptionFilter, ...)
>
> So where do you see the general problem with using exceptions to
> report programming errors?
> And how do you think programming errors should be reported in C++?

Clear-cut theoretical answer, for me, is: code that errs should crash,
preferably with a crash dump and as soon as possible. That's
invaluable for the ease of development, because that helps the most in
finding the source of the problem.

Of course, in practice, things get muddy. Often, once error is
detected, it's already too late (e.g. stranded pointer). OTOH, with
that drastic approach, "user experience" suffers. I'd guess that
numerous coders have been forced by their respective marketing or
whatever departments to try to continue running even though there's
something horribly wrong, and frankly, I can see that point, too.

I personally would not touch most of functions you list there -
problems that cause them to be invoked are way too bad for me to try
to get smart. So quick death there, using the default behavior.
(Luckily, I don't remember when was the last time I got pure e.g.
virtual call error). I do use SetUnhandledExceptionFilter to produce
crash dump, though (but I TerminateProcess immediately after that).

WRT Java situation - I am ambivalent WRT benefits in mixing exceptions
caused by bugs and "legitimate" exceptions (ones caused not but bugs
but rather by "unusual" conditions). I think that such environments
continue even in case of an error-exception is more consequence of
general programming model where all throws, than a conscious decision
to do so.

Goran.
From: Goran on
On Jan 8, 5:40 pm, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
> If you throw an exception that is not CException-derived, then you bypass the MFC handler.

Yes. I think, ideally, an MFC program should abstain from throwing
anything else. (Or, if anything else is possible, it's an error). In
fact, in general, a given piece of C++ code should only have one base
exception class. That's because one does not want catch(type1) {} catch
(unrelatedType2) all over the place, nor does one want to think about
different exception types all the time. That's one thing e.g. Java
gets better It just mandates Throwable, easy. But I had one situation
in C++, where I much enjoyed freedom to define my very own base
exception class not oming from either MFC, ATL or STL.

Luckily, one-base-exception-class is already the case, or achievable,
in MFC code. For example, AFAIK, any exception coming from standard
library is a genuine bug, so it should not happen and does not count.
Exceptions from compiler COM support can be "converted" to MFC-based
exception through a callback hook (I can dig it out, but can't
remember it now). Exceptions of third-party libraries can either
provide similar hook, or be calls to them wrapped and exceptions
rethrown as MFC exceptions. IOW, life in C++ land is full of freedom,
but hard...

> I never understood why it ever made sense for the MFC dispatch loop to catch any
> CException; as pointed out, the program is in an ill-defined state.

No, ill-defined state is far from a general case. Look:

BYTE b[10];
CFile(path, mode).Read(b, 10);

Here, all sorts of things that can go wrong, and will be signaled
through an exception. But there's no ill-defined state to be had. IOW,
when exceptions are used as control flow mechanism in face of
unexpected and/or rare conditions, all is fine. But when exceptions
signal code errors, it's bad. If that's the case, exception can even
do more harm than good (heck, like in this post). That's why I wrote
up there that exceptions are strictly __not__ bug-handling tool.

Goran.
From: Giovanni Dicanio on
"Goran" <goran.pusic(a)gmail.com> ha scritto nel messaggio
news:5a154bf2-ea77-49dc-a680-fa7acdb3f458(a)s31g2000yqs.googlegroups.com...

> Luckily, one-base-exception-class is already the case, or achievable,
> in MFC code. For example, AFAIK, any exception coming from standard
> library is a genuine bug, so it should not happen and does not count.

Goran: could you please clarify this?

The standard library can throw std::bad_alloc in case of allocation failure,
and I think that is not a "genuine bug"... (I would categorize an allocation
error as a form of error condition.)

Or probably I misunderstood you.

Thanks,
Giovanni



From: Joseph M. Newcomer on
I do not believe it could possibly be a "genuine bug". An exception thrown by the
standard library indicates an error. But the source of the error does not necessarily
imply a "bug".

Just looking at stdexcept, it doesn;t even mention bad_alloc as an exception; it mentions

domain_error
(which says it is the basis of all exceptions that report a domain error. AFAIK, this
would mean something like trying to validate credentials on the wrong server...)

invalid_argument
Why is an "invalid argument" necessarily a "bug"? It could also be "bad input", a
condition to be reported and recovered from. Note that if you EVER built any kind of
input-oriented system, you realize that either you have to completely duplicate the
validation of arguments that come from values the user types in, or simply pass it in
blindly, catch the exception, and report to the user that their data is bad. It is NOT a
"bug".

length_error
Could be caused by bad input. In fact, most successful attacks were caused by doing
things that would be caught by out-of-range or length errors, and the correct response is
not to terminate the program (only in Fantasyland is the correct solution always to
terminate the program; in the real world, this is NEVER permitted! It can happen, but
usually it doesn't make sense to allow it to happen!), but to report the bad data,
possibly abort the current transaction, and return control cleanly to a state that allows
the program to progress.

logic_error
See all above comments

out_of_range
See all above comments. Either you have to validate values, or let the library validate
values. If the library throws an exception, you catch it, report the error, and go on
with life. Bug? I don't think so.

runtime_error
Well, that's most things. Not clear how this differs from all other exception classes,
since the number of compile-time exceptions is vanishingly small.

underflow and overflow errors
Often these are expected. Bug, no. Bad data, yes. And certain algorithms actually rely
on hitting overflow or underflow to trigger certain kinds of recovery computations to
ensure convergence.

Building software that runs 24/7 means that NO error condition is allowed to be considered
"fatal", every failure, for WHATEVER cause (bad input, program bug, who cares?) must
result in a clean continuation of execution. I've built systems that recover from
allocation failure, stack overflow, data overruns, etc., and it takes a LOT of work to
make these do clean recovery. We had one where we did storage compaction! Try THAT in
your standard C environment! [No, it is NOT fun! It required very careful programming,
and essentially, all important structures were reachable from a small number of known
roots, and no pointers to ANYTHING were ever retained except in the structures themselves.
Our environment made it possible to discover, in these structures, where the pointers
were. We probably poured 10 programmer-years into this recovery, but the program NEVER
failed! Back in those days, of machines with 256K, running out of memory was a
commonplace problem, and we built an entire virtual VM resembling Windows 1.0 to deal with
this, ca. 1972. And the language wasn't C, but was functionally equivalent to it in all
ways]

By the way, building that system in 1972 led to some of the work in exceptions that
appeared in our later compilers. Trying to build robust software without an exception
mechanism is a losing game.
joe

On Sat, 9 Jan 2010 18:31:19 +0100, "Giovanni Dicanio"
<giovanniDOTdicanio(a)REMOVEMEgmail.com> wrote:

>"Goran" <goran.pusic(a)gmail.com> ha scritto nel messaggio
>news:5a154bf2-ea77-49dc-a680-fa7acdb3f458(a)s31g2000yqs.googlegroups.com...
>
>> Luckily, one-base-exception-class is already the case, or achievable,
>> in MFC code. For example, AFAIK, any exception coming from standard
>> library is a genuine bug, so it should not happen and does not count.
>
>Goran: could you please clarify this?
>
>The standard library can throw std::bad_alloc in case of allocation failure,
>and I think that is not a "genuine bug"... (I would categorize an allocation
>error as a form of error condition.)
>
>Or probably I misunderstood you.
>
>Thanks,
>Giovanni
>
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Goran on
On Jan 9, 6:31 pm, "Giovanni Dicanio"
<giovanniDOTdica...(a)REMOVEMEgmail.com> wrote:
> "Goran" <goran.pu...(a)gmail.com> ha scritto nel messaggionews:5a154bf2-ea77-49dc-a680-fa7acdb3f458(a)s31g2000yqs.googlegroups.com...
>
> > Luckily, one-base-exception-class is already the case, or achievable,
> > in MFC code. For example, AFAIK, any exception coming from standard
> > library is a genuine bug, so it should not happen and does not count.
>
> Goran: could you please clarify this?
>
> The standard library can throw std::bad_alloc in case of allocation failure,
> and I think that is not a "genuine bug"... (I would categorize an allocation
> error as a form of error condition.)
>
> Or probably I misunderstood you.

Whoops! Indeed, you are correct about bad_alloc and I didn't think
that through! Can I change that to "most exceptions", pretty please? I
was thinking about the likes of range_error from a vector and
similar...

Goran.