From: Joseph M. Newcomer on
See below...
On Wed, 6 Jan 2010 00:07:58 -0800 (PST), Goran <goran.pusic(a)gmail.com> wrote:

>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 ;-) ).
****
Consider: scope guard only deals with cleanup of variables that have local scope, and in
fact does not correctly handle a LARGE number of situations. For example

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;
}

Note that "automatic" mechanisms don't handle this, because it is CORRECT for the object
to have a lifetime beyond the scope of the function; that's the whole point of the
function! BUT, if there is an error, the function return won't be seen, because the
exception can go flying by the caller. So the traditional C++ish models, which naively
assume local variables only need local lifetimes, fail.

Consider also the infamous "locking" example:

void Whatever(...)
{
Lock.Acquire(); // where Lock::~Lock releases the lock
... do something
}

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.

"Local cleanup" means "The function performs whatever is required to guarantee its
invariants are maintained", and all known systems (smart pointers, ScopeGuared, etc.) that
give the illusion that they confer perfection on code are not doing this.

I should point out that we started using exceptions in 1968, and one of the modifications
I made to the original design was the notion of "catch all" and "rethrow", even though we
had managed to implement the equivalent of "smart pointers" and "ScopeGuard"
****
>
>(BTW, what you wrote there is the equivalent of a "finally" in...
>ahem... lesser languages. C++ really has no need for finally.)
****
Not quite "finally". Note in my example, a "finally" that did "delete result" would be
erroneous. The "result" value must be returned on successful completion, deleted only if
an exception is passing through)
****
>
>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).
****
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.

You cannot use tecniques such as ScopeGuard when lifetimes of data will exceed scope on
success but the data must be released and other local invariants maintained on failure.
joe
****
>
>Goran.
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Giovanni Dicanio on
"Joseph M. Newcomer" <newcomer(a)flounder.com> ha scritto nel messaggio
news:iuf9k55r23q6h20b5jvuhge6mnf31dvcd4(a)4ax.com...

> Consider: scope guard only deals with cleanup of variables that have local
> scope, and in
> fact does not correctly handle a LARGE number of situations.
> [...]

I agree with Joe: writing *correct* exception-safe code is not trivial, and
RAII is only one step in the direction, e.g. for the basic exception-safety
guarantee (the strong exception-safety guarantee involves transactional
commit/rollback semantics and is even more complex).

Some interesting readings:

Cleaner, more elegant, and wrong
http://blogs.msdn.com/oldnewthing/archive/2004/04/22/118161.aspx

Cleaner, more elegant, and harder to recognize
http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx

C++: do you (really) write exception safe code?
http://stackoverflow.com/questions/1853243/c-do-you-really-write-exception-safe-code


Giovanni


From: Joseph M. Newcomer on
If you throw an exception that is not CException-derived, then you bypass the MFC handler.

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.
joe

On Fri, 8 Jan 2010 07:29:16 -0800 (PST), Peter Schneider <peter.m.schneider(a)gmx.de> wrote:

>On 7 Jan., 11:28, Goran <goran.pu...(a)gmail.com> wrote:
>
>> I thought of one small step forward: override ProcessWndProcException
>> and crash on InvalidArg there. That's far away from the cause, I know,
>> but if you have (or add) some logging to your code, you could get
>> closer to it.
>
>Thanks for this suggestion! It's probably the best I can get.
>Now if only it were possible to re-throw the original exception in C+
>+ ;-)
>
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on
See below...
On Fri, 8 Jan 2010 12:09:05 -0800 (PST), Goran <goran.pusic(a)gmail.com> wrote:

>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.
****
One thing I learned many, many years ago (1976, to be exact): It doesn't matter if it is
right if it fails-soft and recovers cleanly. Seriously. If the goal is to run without
failure, there are two critical approaches
(1) make sure there are no failures
(2) make sure all failures recover in a way that does not impair functionality or
correctness

I spent months trying to achieve (1), only to conclude that we had an intermittent
hardware problem. So I went to (2), and even when the hardware failed, I was able to
recover cleanly. I took the MTBF from 45 minutes to 6 weeks (at which point, everything
was going well, but building power failed when a crane toppled across both the primary
input feed and the backup input feed, which were three feet apart!) We had a hardware
failure at least once a day, which caused an exception to be thrown, and we recovered.

We always harbored the thought that there really was a bug that set a NULL pointer, as
opposed to a memory glitch that returned 0, but after a while it no longer mattered. We
could never find the bug, if it existed. But the system never stopped.

It did take me a year to make this completely bulletproof.

So I do not believe that throwing an exception should terminate a program; rather, I think
throwing exceptions is a well-structured way to create programs that don't fail.

Sometimes, the recovery involved re-certifying the integrity of individual data
structures, and that certification itself could potentially throw exceptions (we had no
way to ask "is this a valid address?" without trying to read it and taking an exception).
I do not think it makes sense to think that terminating a program immediately if an
exception is thrown is the one-and-only possibility. In the real world, I want options to
save state, close files, clean up relevant system state, and if possible, continue correct
operation.

Have you noticed sometimes when Office crashes, it saves the current file in its
best-possible recent state? Not an accident. Adobe's FrameMaker works the same way.
****
>
>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.
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on
See below...
On Mon, 11 Jan 2010 01:26:33 -0800 (PST), Peter Schneider <peter.m.schneider(a)gmx.de>
wrote:

>On 8 Jan., 22:15, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
>> Sometimes, the recovery involved re-certifying the integrity of individual data
>> structures, and that certification itself could potentially throw exceptions (we had no
>> way to ask "is this a valid address?" without trying to read it and taking an exception).
>> I do not think it makes sense to think that terminating a program immediately if an
>> exception is thrown is the one-and-only possibility. �In the real world, I want options to
>> save state, close files, clean up relevant system state, and if possible, continue correct
>> operation.
>>
>> Have you noticed sometimes when Office crashes, it saves the current file in its
>> best-possible recent state? �Not an accident. �Adobe's FrameMaker works the same way.
>
>I don't think anyone suggested that an application should always be
>terminated immediately when an unhandled exception or internal error
>of any kind occurs. I definitely agree that we need to have options
>such as you suggested.
>
>In my opinion it is much easier to fix programming errors when the app
>really crashes (particularly these days when they are reported via
>windows error reporting), ideally after minimizing the damage (e.g.
>saving the user's input).
>
****
WEP is a typical half-assed solution to a real problem. It assumes that the application
will terminate. There appears to be no mechanism for doing a
snapshot-with-immediate-resumption.
joe
****
>With MFCs catch() I don't seem to have that option ...
****
catch is not the place to do this; the interceptor for the exception is where to do it.
joe
****
>
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
 |  Next  |  Last
Pages: 1 2
Prev: CString::GetLength error
Next: Want to set the width