Re: try, finally

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jason,

> How would you handle predictable, common error conditions, then?

In my projects, throwing an exception mean "the application is about to
terminate."

That's using the exception mechanism at the extreme of conservative
programming with exceptions.

Assuming you use exceptions with less draconian policy, the exception
mechanism is not for using as normal flow control.  It really means an
exceptional situation, outside of the normal flow control.

For normal flow control -- such as handling predictable, common error
conditions -- you should use return codes.

One way to have more "in your face" return codes, is to return "smart return
code objects".

A smart return code object has this kind of behavior:
+ wraps a return code
+ if the caller does read (query) the return code object,
  THEN the object marks itself as having been checked
  AND the object's destructor is silent
+ if the caller does not read (query) the return code object,
  AND the return code object does NOT have an error status,
  THEN the object's destructor is silent
+ if the caller does not read (query) the return code object,
  AND the return code object DOES have an error status,
  THEN the object's destructor does "something"
  Where "something" is one or more of...
  + an assert
  + a trace to a log
  + throw an exception

I consider a "smart return code object" to be training wheels for result
codes.  But for larger teams, they become very helpful.

> And what do you consider to be unpredictable and rare?

Any violation of the routine's contractual requirements.

For example, if an int parameter must have the value of 0, 1 or 2, and the
value passed in is something other than 0, 1 or 2.

Any violation of the routine's contractual obligations.

For example, if the routine must put the object in state A or B, but was
unable to do so and the object is in state C (a "never happen" situation).

For example, if the object is in an inconsistent state upon return, such
that the object's invariance is violated.  This can happen if a state change
cannot be completed as a transaction, and enough has happened such that the
state of the object cannot be reverted.  (That's why have transaction based
assignment operator -- perhaps using the swap paradigm -- is so very
useful.)

Any "never happen" situations.  (Where, in the case of my applications,
keeping in mind that throwing an exception means "terminate the application,
forthwith".  So throw an exception where it is appropriate to terminate the
application works as a rule-of-thumb in my application.  Your exception
usage policy will likely be less extreme.)

Any "is it okay if the processing continues (without throwing or returning
an error code) with the detected 'broken axle' condition?"  If it's not
okay, then either throw or return an error code.

> If I was writing code to parse that, and found "root", then
> "something", then "value", but not "data", I would call that a rare...

I presume you are speaking of the "meta-layer" (the decision making layer)
above the parser itself.

In my application, ponder "is this failure such that the application should
be terminated ... or can it be handled in some reasonable failsafe fallback
and the application continue running?"

Also useful is writing your own throw handler such that if a throw happens
it forks the application and core dumps the child (useful to have
"core.<PID>" files enabled).  That's how rarely I expect an exception to
occur, even when using exceptions with less draconian policies than
"terminate the application, forthwith".  And with a core you have a good
snapshot of the application and where things went awry.

Also, once you start using exceptions, you have to be careful too.
Exceptions cannot be thrown through a C barrier.  That means that you cannot
propagate an exception through an OS callback or other C callbacks.  You
cannot propagate an exception outside of a thread's entry routine.  And on
some platforms, you cannot propagate an exception out of the "module" (DLL)
that generated the exception.

> Take Java as an extreme example of the use of exceptions.

Java exceptions are not the same thing as C++ exceptions.

In my opinion, Java exceptions are much more useful, and robust, and can be
used in Java situations where one would not use C++ exceptions in analogous
C++.

> What would your alternative be?

Returning error codes from functions.  Even if it is "messy".

> on failure. In this case, exceptions are a great error return, because
> they can store a lot more information than, say, returning an integer
> from a function. In fact, this is *precisely* what exceptions are
> designed for.

An error code from a function does not need to be an int.  The error code
can be an object that can store a lot more information.

> Yes, I know this. This is precisely why I came here to ask about SEH
> in GCC... SEH is a feature in other compilers that I use precisely to
> prevent the bloat. GCC did not provide it, and now I am looking for an
> alternative. You are preaching to the choir, my friend.

C++ has RAII, which is just as useful, and is standard.  No need for an SEH
compiler extension.

I'm glad you found Boost -- amazingly cool C++ enhancers.  :-)

Sincerely,
--Eljay

Note: Ted Byers is spot on.  I would have answered in exactly the same way
as he did, but I doubt I could have answered as eloquently.

Note: Read Herb Sutter's Exceptional C++.
Also, read Herb Sutter & Andrei Alexandrescu's C++ Coding Standards.


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux