From: Peter Schneider on
Hello,

in AfxCallWndProc MFC catch exceptions derived from CException (in
particular CInvalidArgException which is thrown by some MFC functions
such as CArray::GetAt even though this is undocumented). A message box
will be shown but then the application will continue to run in a
potentially corrupt state.

This makes it hard to find the root cause of an unhandled exception,
particularly when a problem is difficult to reproduce or occurs only
on customer machines, for example.

I'd prefer a normal crash and a good old crash dump showing the call
stack at the time the exception was thrown. Is there a way to achieve
this?

Thanks,
Peter
From: Goran on
On Jan 5, 2:36 pm, Peter Schneider <peter.m.schnei...(a)gmx.de> wrote:
> Hello,
>
> in AfxCallWndProc MFC catch exceptions derived from CException (in
> particular CInvalidArgException which is thrown by some MFC functions
> such as CArray::GetAt even though this is undocumented). A message box
> will be shown but then the application will continue to run in a
> potentially corrupt state.
>
> This makes it hard to find the root cause of an unhandled exception,
> particularly when a problem is difficult to reproduce or occurs only
> on customer machines, for example.

Note however that exception is not unhandled: it is, there's a big try/
catch in MFC window proc ;-).

>
> I'd prefer a normal crash and a good old crash dump showing the call
> stack at the time the exception was thrown. Is there a way to achieve
> this?

I don't know of any, not without massively changing your code to
actually crash when stepping out of bounds (that is, replacing all
calls to GetAt and operator[] with your own function).

What I have to offer thought is a reflection on the past: in the past,
in release builds, MFC used to just continue and let you bork your
memory. Recently (since VS 2005? perhaps), it started throwing. In all
honesty, I prefer old behavior, that could produce a crash more
easily.

Goran.
From: Goran on
On Jan 6, 2:45 am, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
> I can only answer part of your question.
>
> In VS, there is a way to turn on handling exceptions which intercepts them at the point
> where they occur; to enable this, go to Debug >Exceptions.
>
> You might want to consider putting in some exception handlers of your own..  I'd looking at
> Doug Harrison's article on exceptions at
>
>                http://members.cox.net/doug_web/eh.htm
>
> Ultimately, when using exceptions, I found that the only good way to defend is to have
> LOTS of try/catch blocks scattered widely.  One system I worked in too a year of doing
> this before I got every situation covered (and remember: if you write a try, you HAVE to
> have a recovery strategy for the catch, or you haven't solved the problem..  That's what
> takes the time.  In many cases, you have to clean up with something like
>         catch(CException * e)
>            {
>                     ...do local cleanup...
>             throw;
>                    }

No, good code should not have __any__ of these. Local cleanup in C++
is best handled through judicious application of RAII and it's more
powerful cousin, scope guard. ( I don't know why I started pressing
for scope guard here these days ;-) ).

(BTW, what you wrote there is the equivalent of a "finally" in...
ahem... lesser languages. C++ really has no need for finally.)

Application of RAII and scope guard also invalidates the notion that
good code needs lots of try/catch blocks. It doesn't, because most of
the time it will only do local cleanup and not re-throw a different
exception type (but if that's seen as needed, then try/catch it is).

Goran.
From: Goran on
On Jan 6, 6:16 pm, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
> Thing * something(...)
>    {
>     Thing * result = new Thing;
>     ... do something
>     return result;
>    }
>
> Now what happens if an exception is thrown?  We have a dangling pointer..  So you have to
> do
>
> Thing * something(...)
>    {
>     Thing * result = new Thing;
>     try {
>       ... do something
>          }
>     catch(CException * e)
>         {
>          delete result;
>          throw;
>         }

Nah, in this trivial example, appropriate RAII class exist already.

Thing* something(...)
{
std::auto_ptr<Thing> PResult(new Thing);
...
return P.release();
}

>
> Consider also the infamous "locking" example:
>
> void Whatever(...)
>     {
>      Lock.Acquire();  // where Lock::~Lock releases the lock
>      ... do something
>    }

(I'll presume a usual case: Lock is local to a function, there's
additional synchronization object that outlives the function, and Lock
actually operates on that one).

>
> Note how cool!  No need to worry about an internal 'return' failing to release the lock!
> An exception releases the lock!  Now consider the scenario
>
> void Whatever(...)
>    {
>     Lock.Acquire();
>     .. mess around with internal data structure
>     FixUpInternalDataStructure();  // throws an exception
>    }
>
> Note that this does: it releases the lock, saying the structure invariant is maintained,
> when in fact the FixUpInternalDataStructure has failed to put the structure back into its
> correct state and thrown an exception instead.  So the invariant is not maintained, and
> the naive assumption that the code is "correct" because a nice automatic cleanup has
> happend is violated.

You mixed two concerns: locking and data integrity. You want that
"lock is free" also means "data is consistent". Or, if you will, you
want that FixUpUnternalDataStructure has only "basic exception
safety" (http://en.wikipedia.org/wiki/
Exception_handling#Exception_safety) __and__ that locking achieve
that. That's not possible without additional work. So if that's what
you really want, you might try a scope guard and a Lock object that
outlives Whatever, e.g.:

void UnlockOnSuccess(Lock& l)
{
if (!unhandled_exception()) l.Unlock();
}

void Whatever(Lock& l)
{
l.Lock();
ON_BLOCK_EXIT(&UnlockOnSuccess, l);
FixUpUnternalDataStructure();
}

But, IMO correct approach is to __not__ mix the two concerns. That is,
FixUp... should better satisfy "commit or rollback semantics" (I am
again speaking with that Wikipedia article in mind).

(We had this discussion before; as you might remember and see here, I
believe that locking and data consistency are two different concerns
and are best handled differently).

> One of the interesting problems we ran into was the notion of scope of exceptions.  If I
> have a type T, and there is an exception, T::x, which is a protected type, we cannot throw
> this exception, and in fact the following code is erroneous
>
> class T {
>     protected:
>         class x : public CException() {};
>     public:
>         void method() {
>                    submethod();
>          }
>     protected:
>         void submethod() {
>         if(...) throw new x;
>         }
>
> };
>
> It is required that method must do a catch(x * e) because it cannot allow the anonymous
> (outside the class) exception T::x to escape.  It can simply return, or it can throw an
> exception whose namespace is presumably visible in the caller.  So it must throw a
> different exception type.  In our languages, exception names always had global scope, but
> we learned to treat them as local scope names to maintain modularity.

That's only partially true. In case of MFC exceptions, it's largely
false, because they are supposed to be used polymorphically (you see
how GetErrorMessage and ReportError are virtual? what() of standard
library, too). So for the majority of cases, exact exception type
should be irrelevant, hence type visibility won't matter. That is of
course not true for, IME(xperience) rare, cases where code indeed does
want to catch a specific exception type and do something specific.

Goran.
From: Peter Schneider on
I completely agree that correct exception handling is not trivial and
as we can see from the interesting discussion in this thread, it's
often controversial, too.

But I think I need to clarify my intial question a bit because the
discussion is not directly related to it anymore.

I am aware that the CExceptions are handled by a try/ catch in MFC
window proc if the application code does not handle them. But in my
opinion and seemingly also in Goran's, this handler is doing more harm
than good. If the app didn't handle it and it gets caught here, it's
pretty likely that the app is in an undefined state now. I am
primarily concerned with exceptions which represent what Java calls
run-time exceptions: exceptions which are thrown when something
occurred which is typically cuased by a programming error.
CInvalidArgException which can be thrown by CArray::GetAt is such an
example. In my opinion, it doesn't make sense to write handlers for
this everywhere (for example, each time GetAt is called or in each top-
level message handler). If GetAt is called with an invalid argument
this means that there is a programming error of some kind and no
reasonable way to deal with this in a general fashion. But because MFC
"swallows" these exceptions, it get's unnecessarily hard to find such
problems if they do occur. Particularly if the problem is difficult to
reproduce and only occurs on end-user machines. There won't be a
windows error report (WER). Only complaints about a message box
indicating something like "an invalid arg was detected".

So my question should have been: Is there a way to work around this
MFC exception handler and to get normal crashes instead without having
to change lots of code?

But I am afraid Goran already answered it here:

> I don't know of any, not without massively changing your code to
> actually crash when stepping out of bounds (that is, replacing all
> calls to GetAt and operator[] with your own function).

Peter