Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Error codes vs. exceptions

244 views
Skip to first unread message

mike3

unread,
May 29, 2012, 12:15:00 AM5/29/12
to
Hi.

I've heard about this, and wonder when is it right to use codes, and
when to use exceptions for reporting errors? I've heard various stuff,
such as that exceptions should only be used to indicate "exceptional"
conditions. Yet what does that mean? I've heard that, e.g. a user
inputting invalid input should not be considered "exceptional", but
something like running out of memory should be. Does this mean that if
we have a program, and we have a "parse()" function that parses a
string input by the user, that this function should return an error
code on parse failure, instead of throwing an exception? Yet we'll
probably also come across places where it's good to use an exception,
in the same program! Which means we get into _mixing error codes and
exceptions_. And what's the best way to do that?

Also, how exactly does one go about determining what is and is not
"exceptional"? Two examples were mentioned of things exceptional and
non-exceptional, but what about something else, like say in a game,
where you have a grid representing a game level, and a request for a
tile of the level is made with a coordinate that is off the map (like
a 64x64 map and something requests a tile at (100, 100).). Would it be
OK for the function working on the tile to throw? Or should it give an
"out of range" error code? And as for that mixing: consider, e.g. C++
and probably many other languages: a function has a single definite
return type. Suppose our grid had a function that extracts an
attribute from a cell. What to do when there's an out-of-bounds
request? Throw exception? See, what I've currently been doing, and
it's probably silly, is to use exceptions when our function needs to
return a value, and error codes when it could otherwise return "void".
This doesn't seem like a good idea. But what to do? Make every
function return an error code, using pointers to output variables to
store output, and only use exceptions for a rare few kinds of "system-
related" error? Yet one can hardly deny the niceness of being able to
say "x = f() + <foo>" (inside a "try" block, perhaps) instead of

if(f(&x) != SUCCESS)
{ // handle error }
x += foo;

:)

Note how we can easily get LONG methods full of repeated code with
error codes (repeated error handlers to handle similar errors at
various function calls calling error-code-emitting functions, if one
wants to be more graceful than simply aborting with an error to the
next level up (which complicates what error codes a function can
return, since it can return its own codes in addition to those
returned by the functions below it, and those may have functions below
THEM, and so on...).). And who likes duplicated code? eww. This seems
a disadvantage of error codes.

Or, and this is what I've been thinking of, use exceptions for every
error that the user does not have control over, like invalid input
strings. Would that be OK or excessive use of exceptions? And if we
are to mix error codes and exceptions, does this mean we should have
the lists of codes and exceptions correspond + a translator to
translate between the two?

BGB

unread,
May 29, 2012, 1:10:20 AM5/29/12
to
On 5/28/2012 11:15 PM, mike3 wrote:
> Hi.
>
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors? I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean? I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional", but
> something like running out of memory should be. Does this mean that if
> we have a program, and we have a "parse()" function that parses a
> string input by the user, that this function should return an error
> code on parse failure, instead of throwing an exception? Yet we'll
> probably also come across places where it's good to use an exception,
> in the same program! Which means we get into _mixing error codes and
> exceptions_. And what's the best way to do that?
>

maybe more like this:
use error codes if it can be reasonably done so;
use exceptions if error codes wont really work.

usually, this means returning an error code if the operation can be
handled as a no-op and otherwise the program can continue as normal
(like, "well, that didn't work").

use an exception if this represents a case where normal operation can no
longer reasonably continue (all action past this point is no longer
likely to be in a valid state, such as detecting that some internal
program state is critically wrong).

if it is not clear to use, probably I would opt with error codes.
(usually, when an exception is needed, it is "fairly obvious").
if the function returns a void, use it to return an error code;
if the function returns a pointer, one can potentially return NULL, and
have another operation to fetch the actual error code (stored off in a
variable somewhere);
if the function returns a number, then it is a little harder, sometimes
it can be ">=0 for success, <0 for error", but if the function may
return the full range, it is a bit harder.

one way I have handled it is to have it be similar to the pointer case,
where a certain value (0 or -1), "may" represent an error, and whether
or not it really does is determined by retrieving the error code.

NaN is also a possible error value for floating-point numbers, but is
rarely used this way.

mike3

unread,
May 29, 2012, 1:41:54 AM5/29/12
to
On May 28, 11:10 pm, BGB <cr88...@hotmail.com> wrote:
<snip>
> maybe more like this:
> use error codes if it can be reasonably done so;
> use exceptions if error codes wont really work.
>

So does this mean it is OK to use exceptions for errors in, say, a
constructor, regardless of what the error is?

BGB

unread,
May 29, 2012, 2:34:44 AM5/29/12
to
potentially.

if for some reason the constructor can't actually do its thing, this may
be a reasonable option.

usually, I prefer "graceful" handling whenever possible, meaning that an
exception would only be used in this case if the produced object would
be invalid and there is no "more graceful" way to handle the situation.

there is no solid rules to define this, and it may need to be evaluated
on a case-by-case basis.

Marcel Müller

unread,
May 29, 2012, 3:08:57 AM5/29/12
to
On 29.05.2012 06:15, mike3 wrote:
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors? I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean?

Finally it is up to the programmer to take the decision.
But there are some performance aspects as well as some considerations
about exception safe code.

Depending on your language, throwing an exception could be an expensive
task. C++ is yet mostly harmless, but managed languages like Java or
*.NET create an expensive stack trace at the time of the exception
construction or at throw respectively. So it is in general a bad advise
to throw and catch exceptions over and over in loops.

Furthermore exceptions are an unexpected way of changing the execution
flow. While this is intended in most cases there are some pitfalls. Most
code is not fully exception safe. I.e. is shows undefined behavior if
the exception occur at the evaluation of certain (sub-)expressions.
Writing fully exception safe code can be almost as complicated than
writing thread-safe code.
So in fact you should know which of your functions throw exceptions and
which don't. At the end, the advantage of the exceptions, easy code,
might no longer be that large.


> I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional", but
> something like running out of memory should be.

Well, I dislike general statements like this.

If a wrong user input causes the normal execution flow to be interrupted
at a certain point, a exception might be quite OK. If the execution
continues with the next input box that might be also become red,
exceptions might not hit the nail on the head. You remember, no catch in
a loop (over the controls).


> Also, how exactly does one go about determining what is and is not
> "exceptional"?

You can't determine this. You have to /define/ this.
What causes your program to abandon normal operation (for a while)?


> non-exceptional, but what about something else, like say in a game,
> where you have a grid representing a game level, and a request for a
> tile of the level is made with a coordinate that is off the map (like
> a 64x64 map and something requests a tile at (100, 100).). Would it be
> OK for the function working on the tile to throw?

Does this abort normal program flow?
What is the proper action to be taken next?

> Or should it give an
> "out of range" error code? And as for that mixing: consider, e.g. C++
> and probably many other languages: a function has a single definite
> return type. Suppose our grid had a function that extracts an
> attribute from a cell. What to do when there's an out-of-bounds
> request? Throw exception?

Unless your semantics have some default value which could be used to
continue processing, you won't come around to abort the execution flow
here. But it could be a good advice to check this before you call any
function that will not work properly. I.e. you could turn the array
bounds condition into a precondition which could be checked by an assertion.


> But what to do? Make every
> function return an error code, using pointers to output variables to
> store output, and only use exceptions for a rare few kinds of "system-
> related" error?

Don't do that. Use exception where they make the code easier to read and
easier to understand. And if you run into performance problems, then
look for a work around. But in C++ this is unlikely as long as you do
not abuse them extensively.
A prominent exception to this rule are APIs that can cross language
boundaries. In this case you mostly have no chance. You need error codes.

Another rule of thumb: if throw and catch are close together with
respect to the call stack it is more likely that an error code fit your
needs. If they are well separated, then exceptions might be preferable.


[...]
> Would that be OK or excessive use of exceptions? And if we
> are to mix error codes and exceptions, does this mean we should have
> the lists of codes and exceptions correspond + a translator to
> translate between the two?

Converting an error code into an exception might be a good idea. But the
other way around is most likely not.

And another rule of thumb: the number of exceptions thrown during the
processing of a complete request should be finite. I.e. it must not
scale with the amount of data processed.


Marcel

Dmitry A. Kazakov

unread,
May 29, 2012, 3:37:20 AM5/29/12
to
On Mon, 28 May 2012 21:15:00 -0700 (PDT), mike3 wrote:

> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors?

Return code should be used under no circumstances.

1. return codes cripple design on the callee's side
2. they cuase massive code replication contaminating the source program on
the client side
3. they are unmaintainable (consider adding/removing a code value)
4. they represent a distributed overhead causing less efficient programs on
most of existing architectures

> I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean?

Exceptional condition is when normal continuation would be impossible.

As an example consider zero divide. It is exceptional because for x /=0
there is no numeric value y such that y * 0 = x.

> I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional",

That depends on whether continuation is possible. E.g. an improperly
encoded UTF-8 character may be replaced by '?' or raise an exception
causing the caller to sort things out. The choice depends on the
application. The key question is: who is responsible for recovery?

> but
> something like running out of memory should be. Does this mean that if
> we have a program, and we have a "parse()" function that parses a
> string input by the user, that this function should return an error
> code on parse failure, instead of throwing an exception?

When the result would be invalid, parse should raise an exception, e.g.
Syntax_Error with an appropriate message and error location indication.

> Also, how exactly does one go about determining what is and is not
> "exceptional"?

You look at the contract of the thing. e.g. of operation /. If there is no
way to implement the contract, that is exceptional [*]. Another way to put
it: an exception is to propagate from where there is not enough information
to handle it without crippling the design. When you implement file read
operation. At the file end, you don't know what to do. You cannot continue
reading, so you raise End_Error. The caller should have information how to
react. If it does not, it let the exception propagate or raise another
exception, etc.

-----------
* Exception fixes the contract by adding itself as a possible outcome.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

io_x

unread,
May 29, 2012, 4:00:48 AM5/29/12
to

"mike3" <mike...@yahoo.com> ha scritto nel messaggio
news:4f571f71-55ca-4922...@kw17g2000pbb.googlegroups.com...
> Hi.
>

if one use exception that one miss the controll of his program


Jorgen Grahn

unread,
May 29, 2012, 8:24:35 AM5/29/12
to
["Followup-To:" header set to comp.lang.c++.]
On Tue, 2012-05-29, mike3 wrote:
> Hi.
>
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors?

Are you asking specifically about C++? I will assume "yes", but I get
a bit confused by your crossposting to comp.programming -- what's the
proper use of exceptions varies between languages (and cultures).

> I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean? I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional", but
> something like running out of memory should be. Does this mean that if
> we have a program, and we have a "parse()" function that parses a
> string input by the user, that this function should return an error
> code on parse failure, instead of throwing an exception? Yet we'll
> probably also come across places where it's good to use an exception,
> in the same program! Which means we get into _mixing error codes and
> exceptions_. And what's the best way to do that?
>
> Also, how exactly does one go about determining what is and is not
> "exceptional"?

I don't think you should try use the idea of "exceptional" conditions
as a strict rule to apply. IIRC it was something Stroustrup came up with
to explain how he thinks about it, but it's vague; you can debate
what's exceptional or not for years.

Some things are hard to set up general rules for. You have to deal
with them on a case-by-case basis.

> Two examples were mentioned of things exceptional and
> non-exceptional, but what about something else, like say in a game,
> where you have a grid representing a game level, and a request for a
> tile of the level is made with a coordinate that is off the map (like
> a 64x64 map and something requests a tile at (100, 100).). Would it be
> OK for the function working on the tile to throw? Or should it give an
> "out of range" error code?

To me, it has more to do with things like:
- are you going to take steps elsewhere to make out-of-bounds
requests not happen? E.g. document "it's up to the caller
to stay on the map"?
- can it make sense not to handle the error locally?
- would an error code be an unreasonable burden at the calling site,
e.g. you really want to be able to say things like
"get_tile(position).invert();" ?

But it seems you say more or less this below!
As far as I can tell, you think about this pretty much like I do,
except you're still trying to formalize it into some system of rules.
Try not to do that for a while, and see how it feels.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Adam Skutt

unread,
May 29, 2012, 10:16:37 AM5/29/12
to
On May 29, 1:10 am, BGB <cr88...@hotmail.com> wrote:
> On 5/28/2012 11:15 PM, mike3 wrote:
>
> > Hi.
>
> > I've heard about this, and wonder when is it right to use codes, and
> > when to use exceptions for reporting errors? I've heard various stuff,
> > such as that exceptions should only be used to indicate "exceptional"
> > conditions. Yet what does that mean? I've heard that, e.g. a user
> > inputting invalid input should not be considered "exceptional", but
> > something like running out of memory should be. Does this mean that if
> > we have a program, and we have a "parse()" function that parses a
> > string input by the user, that this function should return an error
> > code on parse failure, instead of throwing an exception? Yet we'll
> > probably also come across places where it's good to use an exception,
> > in the same program! Which means we get into _mixing error codes and
> > exceptions_. And what's the best way to do that?
>
> maybe more like this:
> use error codes if it can be reasonably done so;
> use exceptions if error codes wont really work.

Nonsense. A function should only return a value if the caller can use
the return value to further its own computation. It is very rare for
an error code to be useful to the caller, much less all of the codes
returned by a function. Hence, they should be exceptions because
stack unwinding will be needed.

> usually, this means returning an error code if the operation can be
> handled as a no-op and otherwise the program can continue as normal
> (like, "well, that didn't work").

If the error can and should be treated as a no-op then there is no
reason to return anything at all.

> if it is not clear to use, probably I would opt with error codes.
> (usually, when an exception is needed, it is "fairly obvious").

This is precisely backwards. Return values should have clear,
obvious, and unambiguous usage. If you cannot determine what the
caller would do with the return value, then odds are good they will
"pass the buck" and therefore an exception is the right thing.

> > Or, and this is what I've been thinking of, use exceptions for every
> > error that the user does not have control over, like invalid input
> > strings. Would that be OK or excessive use of exceptions? And if we
> > are to mix error codes and exceptions, does this mean we should have
> > the lists of codes and exceptions correspond + a translator to
> > translate between the two?
>
> if the function returns a void, use it to return an error code;

This is nonsense. I assume you meant, "Change the return type to be
an error code" but I honestly have no clue.

> if the function returns a pointer, one can potentially return NULL, and
> have another operation to fetch the actual error code (stored off in a
> variable somewhere);

This requires either extra parameters or a lot of ugly work to create
thread-safe behavior. Which is why error codes are a bad idea. Using
them simply pollutes calling code for no clear benefit, especially
when stack unwinding is necessary (which is the most common case).

Adam

Adam Skutt

unread,
May 29, 2012, 10:42:11 AM5/29/12
to
On May 29, 12:15 am, mike3 <mike4...@yahoo.com> wrote:
> Hi.
>
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors?

You should almost always use exceptions. The main reason to use error
codes in C++ would be due to compatibility concerns with C frameworks,
or so that C-compatible wrappers can be provided for your C++ code.

I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean?

It means that anything other than what the function would return if it
completed normally, or did not fail. The question you should ask
yourself is: "What would the function return if it simply could not
fail?" The answer to that question (if any) is the return value.
Anything else should almost certainly be an exception. Anything that
will (really might) require stack unwinding to handle should also be
an exception.

> I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional", but
> something like running out of memory should be. Does this mean that if
> we have a program, and we have a "parse()" function that parses a
> string input by the user, that this function should return an error
> code on parse failure, instead of throwing an exception?

The result of a parse function is a data structure representing the
parsed input (e.g., a parse tree). If the function cannot produce a
parse tree, and the caller needs a parse tree to continue on their
computation (i.e., failure cannot be sensibly replaced with an empty
tree) than an exception should be thrown.

In this case, it's not necessarily guaranteed that the function that
called parse() will be the function that prompts the user for input.
It's also not guaranteed that prompting the user for replacement input
is possible. If your input comes from a pipe, then you have no way to
prompt the user and only one input. In this case, termination is
likely the only sensible response for the parse failure. An exception
should be used here since stack winding is not only a probable
response, but a likely response, to a parsing failure.

> Yet we'll
> probably also come across places where it's good to use an exception,
> in the same program! Which means we get into _mixing error codes and
> exceptions_. And what's the best way to do that?

Don't. If you must, it is probably best to convert error codes to
exceptions and not vice-versa. This should only come up if you must
interface with legacy systems or C libraries.

>
> Also, how exactly does one go about determining what is and is not
> "exceptional"? Two examples were mentioned of things exceptional and
> non-exceptional, but what about something else, like say in a game,
> where you have a grid representing a game level, and a request for a
> tile of the level is made with a coordinate that is off the map (like
> a 64x64 map and something requests a tile at (100, 100).). Would it be
> OK for the function working on the tile to throw?

Absolutely.

> Or should it give an "out of range" error code?

Doubtful. Code that provided an invalid input either has a bug (so
must be fixed) or received invalid input from the user. In either
case, an exception is better way to structure a response to the error
condition.

> Yet one can hardly deny the niceness of being able to
> say "x = f() + <foo>" (inside a "try" block, perhaps) instead of
>
> if(f(&x) != SUCCESS)
>  { // handle error }
> x += foo;
>
> :)
>

Precisely why one shouldn't use error codes.

> Or, and this is what I've been thinking of, use exceptions for every
> error that the user does not have control over, like invalid input
> strings. Would that be OK or excessive use of exceptions?

If I understood you, then buggy functions require program termination
to replace the buggy application[1]. Exceptions will unwind the stack
to terminate the program. Therefore, one should use an exception in
response to invalid input that didn't come from the user.

Though one should also use exceptions to signify invalid input that
did come from the user, because input is rarely accepted in the exact
same function that it is validated.

> And if we
> are to mix error codes and exceptions, does this mean we should have
> the lists of codes and exceptions correspond + a translator to
> translate between the two?

No.

Adam

[1] Typically, a few unique systems aside.

BGB

unread,
May 29, 2012, 10:45:33 AM5/29/12
to
On 5/29/2012 9:16 AM, Adam Skutt wrote:
> On May 29, 1:10 am, BGB<cr88...@hotmail.com> wrote:
>> On 5/28/2012 11:15 PM, mike3 wrote:
>>
>>> Hi.
>>
>>> I've heard about this, and wonder when is it right to use codes, and
>>> when to use exceptions for reporting errors? I've heard various stuff,
>>> such as that exceptions should only be used to indicate "exceptional"
>>> conditions. Yet what does that mean? I've heard that, e.g. a user
>>> inputting invalid input should not be considered "exceptional", but
>>> something like running out of memory should be. Does this mean that if
>>> we have a program, and we have a "parse()" function that parses a
>>> string input by the user, that this function should return an error
>>> code on parse failure, instead of throwing an exception? Yet we'll
>>> probably also come across places where it's good to use an exception,
>>> in the same program! Which means we get into _mixing error codes and
>>> exceptions_. And what's the best way to do that?
>>
>> maybe more like this:
>> use error codes if it can be reasonably done so;
>> use exceptions if error codes wont really work.
>
> Nonsense. A function should only return a value if the caller can use
> the return value to further its own computation. It is very rare for
> an error code to be useful to the caller, much less all of the codes
> returned by a function. Hence, they should be exceptions because
> stack unwinding will be needed.
>

not always, it depends.

if you need to unwind the stack either way, then an exception may make
sense. if not, it is probably not a good answer.


>> usually, this means returning an error code if the operation can be
>> handled as a no-op and otherwise the program can continue as normal
>> (like, "well, that didn't work").
>
> If the error can and should be treated as a no-op then there is no
> reason to return anything at all.
>

usually, the error code will indicate a success/failure in this case.

it is often useful to be able to detect "well, that didn't work",
without needing to be like "on no, stuff has gone terribly wrong".


an example is trying to open a file and searching through a path:
the program may try opening the file along various paths, and see if any
of them work;
in this case, we want to know whether or not the file has been opened
successfully, without needing to catch for every iteration of the loop.


>> if it is not clear to use, probably I would opt with error codes.
>> (usually, when an exception is needed, it is "fairly obvious").
>
> This is precisely backwards. Return values should have clear,
> obvious, and unambiguous usage. If you cannot determine what the
> caller would do with the return value, then odds are good they will
> "pass the buck" and therefore an exception is the right thing.
>

often, if one is using an error code, the operation was probably just
handled as a no-op anyways.

one can use an exception if the situation is sufficiently critical to
where the caller merely carrying on as before would not be a desirable
outcome.

very often, there is no reason to care, and it is better to not burden
the caller with the results, except when they actually care whether or
not the operation succeeded.


>>> Or, and this is what I've been thinking of, use exceptions for every
>>> error that the user does not have control over, like invalid input
>>> strings. Would that be OK or excessive use of exceptions? And if we
>>> are to mix error codes and exceptions, does this mean we should have
>>> the lists of codes and exceptions correspond + a translator to
>>> translate between the two?
>>
>> if the function returns a void, use it to return an error code;
>
> This is nonsense. I assume you meant, "Change the return type to be
> an error code" but I honestly have no clue.
>

fair enough, that could have been written better.

I was responding in context of a prior statement, which basically said
that the OP was using return codes in cases where the function would
otherwise return void.

so, in this case, a person might consider using a return code instead of
a void.


>> if the function returns a pointer, one can potentially return NULL, and
>> have another operation to fetch the actual error code (stored off in a
>> variable somewhere);
>
> This requires either extra parameters or a lot of ugly work to create
> thread-safe behavior. Which is why error codes are a bad idea. Using
> them simply pollutes calling code for no clear benefit, especially
> when stack unwinding is necessary (which is the most common case).
>

I disagree that stack-unwinding is the most common case.
IME, no-op is the most common case, and if the error code is even
checked, it is usually done so to determine a success/failure status (so
that the caller logic can determine whether or not to try a different
option, ...).

as for "in a variable somewhere":
typically, this would be an object field or thread-local variable.

an example would be, say, an object with an "obj->getError()" method or
similar, or a "fooGetError()" function which returns the contents of a
TLS variable, ...


then it is thread-safe...

I didn't say here that it would be a global variable or similar, which
wouldn't be thread-safe.

Adam Skutt

unread,
May 29, 2012, 11:20:33 AM5/29/12
to
On May 29, 10:45 am, BGB <cr88...@hotmail.com> wrote:
> On 5/29/2012 9:16 AM, Adam Skutt wrote:
> > On May 29, 1:10 am, BGB<cr88...@hotmail.com>  wrote:
> >> maybe more like this:
> >> use error codes if it can be reasonably done so;
> >> use exceptions if error codes wont really work.
>
> > Nonsense.  A function should only return a value if the caller can use
> > the return value to further its own computation.  It is very rare for
> > an error code to be useful to the caller, much less all of the codes
> > returned by a function.  Hence, they should be exceptions because
> > stack unwinding will be needed.
>
> not always, it depends.

On what, exactly?
>

> if you need to unwind the stack either way, then an exception may make
> sense.

I fail to see how making the programmer manually do what the language
does automatically is worthwhile. You're going to have to give
examples, and if they're not relevant to general-case programming then
please don't waste anyone's time.


> if not, it is probably not a good answer.
>

Why? You claim this as a tautology and provide zero evidence. The OP
quite clearly and plainly pointed out many problems with using error
codes, which you have utterly failed to rebut nor managed to
demonstrate any positive aspects that allow us to overlook their
flaws.

> >> usually, this means returning an error
code if the operation can be
> >> handled as a no-op and otherwise the program can continue as normal
> >> (like, "well, that didn't work").
>
> > If the error can and should be treated as a no-op then there is no
> > reason to return anything at all.
>
> usually, the error code will indicate a success/failure in this case.
>
> it is often useful to be able to detect "well, that didn't work",
> without needing to be like "on no, stuff has gone terribly wrong".

Huh? This is a complete non-sequitur, as best as I can tell. If I
call a function x() and its behavior is to either: a) succeed b) do
nothing, then why would it ever need to return a status code?

Of course, your original statement didn't really make any sense
either, so it's quite likely I simply have no idea what you were
trying to say in the first place.

>
> an example is trying to open a file and searching through a path:
> the program may try opening the file along various paths, and see if any
> of them work;
> in this case, we want to know whether or not the file has been opened
> successfully, without needing to catch for every iteration of the loop.
>

Nonsense. There's never a need to "detect[ing] 'well, that didn't
work', without needing to be like 'on no, stuff has gone terribly
wrong'." This would be because the difference between the a retryable
error and a fatal error is entirely in the hands of the calling code,
not the called function. The response of the file open function should
be the same in either case, because it has no clue what is
appropriate.

You claim an catch block is inappropriate here, but you give no reason
why. I fail to see any reason why it is inappropriate whatsoever. It
doesn't even take up more space over if/else in your example.

> often, if one is using an error code, the operation was probably just
> handled as a no-op anyways.

Which is another reason why error codes are bad, there's a good chance
the programmer will ignore them, leading to undefined behavior later
on.

>
> one can use an exception if the situation is sufficiently critical to
> where the caller merely carrying on as before would not be a desirable
> outcome.
>

Except it is generally impossible for the called function to know
whether the caller wishes to carry on afterwards or not. Hence why
you should only return input that is useful to everyone and toss an
exception otherwise. People who wish to carry on can install catch
blocks. Everyone else gets precisely what they want.

> very often, there is no reason to care, and it is better to not burden
> the caller with the results, except when they actually care whether or
> not the operation succeeded.

Which is exactly what exceptions accomplish! The fact that my code
continued executing at the next statement means that the called
function succeeded. It also means I never have to worry about
"exceptional" conditions unless I can actually provide a meaningful
response to the condition. If I cannot, then I can pretend that it
does not exist and go on with my lives.

This results in less code, and practically never more code, for the
caller and called function. On that basis alone, exceptions are
superior.

> I disagree that stack-unwinding is the most common case.

You're welcome to present evidence otherwise but you're going to be
hard pressed to do so.

> IME, no-op is the most common case, and if the error code is even
> checked,

If you're going to argue from this basis, you first have to show that
it is correct to ignore the error codes. Tons of software ignores
error codes even when it is not correct to do so. You're quite
honestly adding to your already enormous burden.

> it is usually done so to determine a success/failure status (so
> that the caller logic can determine whether or not to try a different
> option, ...).

Or clean it's resources and manually unwind. Or just as likely,
because that's so difficult to do manually, call abort() or a similar
function to end the world.

>
> as for "in a variable somewhere":
> typically, this would be an object field or thread-local variable.
>
> an example would be, say, an object with an "obj->getError()" method or
> similar, or a "fooGetError()" function which returns the contents of a
> TLS variable, ...
>
> then it is thread-safe...
>

Both are considerable amounts of work for totally unclear benefit.

> I didn't say here that it would be a global variable or similar, which
> wouldn't be thread-safe.

You described essentially the traditional C errno interface, which
requires considerable gymnastics to achieve thread-safety.

Adam

BGB

unread,
May 29, 2012, 2:47:55 PM5/29/12
to
On 5/29/2012 10:20 AM, Adam Skutt wrote:
> On May 29, 10:45 am, BGB<cr88...@hotmail.com> wrote:
>> On 5/29/2012 9:16 AM, Adam Skutt wrote:
>>> On May 29, 1:10 am, BGB<cr88...@hotmail.com> wrote:
>>>> maybe more like this:
>>>> use error codes if it can be reasonably done so;
>>>> use exceptions if error codes wont really work.
>>
>>> Nonsense. A function should only return a value if the caller can use
>>> the return value to further its own computation. It is very rare for
>>> an error code to be useful to the caller, much less all of the codes
>>> returned by a function. Hence, they should be exceptions because
>>> stack unwinding will be needed.
>>
>> not always, it depends.
>
> On what, exactly?

what the code does.

>>
>
>> if you need to unwind the stack either way, then an exception may make
>> sense.
>
> I fail to see how making the programmer manually do what the language
> does automatically is worthwhile. You're going to have to give
> examples, and if they're not relevant to general-case programming then
> please don't waste anyone's time.
>

ok, consider a function:
byte *Foo_ReadInFile(char *name, int &sz);

which returns NULL if the file failed to load.

now, we have a path like:
char *foo_basepaths[256];
int foo_num_basepaths;

...


SomeObjectType *Foo_LoadSomeFileData(char *name)
{
char tb[256];
SomeObjectType *tmp;
char *buf;
int i, sz;

for(i=0, buf=NULL; !buf && i<foo_num_basepaths; i++)
{
snprintf(tb, 256, "%s/%s", foo_basepaths[i], name);
buf=Foo_ReadInFile(tb, sz);
//would we rather have had ReadInFile throw here?
}

if(!buf)
{
//what do we do here, return or throw
return(NULL); //ok, how about we let caller decide?
}

tmp=Foo_ParseObjectFromBuffer(buf, sz);
//now, what here?
return(tmp); //ok, return whatever we got.
}

and, in the caller:
SomeObjectType *Baz_TryLoadSomeData(char *name)
{
char tb[256];
SomeObjectType *tmp;

//see if we can load it as a ".foo" file.
snprintf(tb, 256, "%s.foo", name);
tmp=Foo_LoadSomeFileData(name);
if(tmp)return(tmp); //got something

//well, is is a ".bar" file?
snprintf(tb, 256, "%s.bar", name);
tmp=Bar_LoadSomeFileData(name);
if(tmp)return(tmp); //got something

...

//ok, couldn't find anything, what now?
//maybe?
baz_errno=BAZ_COULDNTFINDFILE;
return(NULL);
}

and so on...


a more concrete example:
consider we are trying to load a 3D model, but don't know in advance
what type of 3D model we are trying to load.

or, we are trying to load a graphic image, but were not given the full
path or the file extension (it could be in one of several locations, or
a PNG, or a JPG, or a BMP, or a TGA, ...).

sometimes, the graphic loading may itself be conditional, say:
did this texture have a normal-map image?
we know it didn't, if none could be loaded, but otherwise it is no big
deal (the texture is used without a normal-map).


an alternate scenario would be, say, if one particular branch of a
programs' drawing code depends on shaders, but the user's system doesn't
have shaders (say, because they have an old/crappy video card)?

well, simplest option would just be to return an error (like, "hey, this
wont work"), with the application falling back to an alternate path:
"well, can we draw it without the shaders then?".

then, if this fails, maybe then something is broken, then one can throw
an exception, or maybe it will end up in the main loop with an error
status "hey, the rendering failed", then the main loop might decide
"well, the renderer apparently isn't working, so have the application exit".

now, exceptions could also work here, say the first piece of logic
throws a "DontHaveShaders" exception or similar, and some code up the
tree catches it and uses the alternate rendering path, but is this less
effort, or more efficient?...


the alternative strategy would be to always do things in the caller, like:
if(foo->DoWeHaveShaders())
{
foo->DoItWithShaders();
}else
{
foo->DoItWithoutShaders();
}


but, this may require separate functions to handle checking and
performing the operation, rather than say:

if(foo->DoItWithShaders()<0)
{
if(foo->DoItWithoutShaders()<0)
{
//failed to render anything
return(FOO_FAILEDTORENDER);
}
}
return(FOO_SUCCESS);


>
>> if not, it is probably not a good answer.
>>
>
> Why? You claim this as a tautology and provide zero evidence. The OP
> quite clearly and plainly pointed out many problems with using error
> codes, which you have utterly failed to rebut nor managed to
> demonstrate any positive aspects that allow us to overlook their
> flaws.
>

I say it depends on the situation.

and I am not saying that one doesn't use exceptions, only that a person
may need to evaluate it based on which is more likely to be more
convenient in a given situation.


I am not saying anything is universal rules here, but all depends on
whatever is more convenient at the moment.


>>>> usually, this means returning an error
> code if the operation can be
>>>> handled as a no-op and otherwise the program can continue as normal
>>>> (like, "well, that didn't work").
>>
>>> If the error can and should be treated as a no-op then there is no
>>> reason to return anything at all.
>>
>> usually, the error code will indicate a success/failure in this case.
>>
>> it is often useful to be able to detect "well, that didn't work",
>> without needing to be like "on no, stuff has gone terribly wrong".
>
> Huh? This is a complete non-sequitur, as best as I can tell. If I
> call a function x() and its behavior is to either: a) succeed b) do
> nothing, then why would it ever need to return a status code?
>
> Of course, your original statement didn't really make any sense
> either, so it's quite likely I simply have no idea what you were
> trying to say in the first place.
>

fallback logic.


whenever something doesn't work, the logic can fallback to trying an
alternate (less preferred) strategy, usually until something either
works, or all immediately available options are exhausted.


often, using an exception will make more sense if the situation is more
like: it either has to work, or things can not continue.

but, this likely depends a lot more on what the program is doing.


>>
>> an example is trying to open a file and searching through a path:
>> the program may try opening the file along various paths, and see if any
>> of them work;
>> in this case, we want to know whether or not the file has been opened
>> successfully, without needing to catch for every iteration of the loop.
>>
>
> Nonsense. There's never a need to "detect[ing] 'well, that didn't
> work', without needing to be like 'on no, stuff has gone terribly
> wrong'." This would be because the difference between the a retryable
> error and a fatal error is entirely in the hands of the calling code,
> not the called function. The response of the file open function should
> be the same in either case, because it has no clue what is
> appropriate.
>
> You claim an catch block is inappropriate here, but you give no reason
> why. I fail to see any reason why it is inappropriate whatsoever. It
> doesn't even take up more space over if/else in your example.
>

I disagree.

trying things and seeing what works and what doesn't is actually fairly
common IME.

this is partly because some things are fairly common, like performing an
operation with only partial information, and the program may have to
probe around a little to figure out how exactly to go about doing it.


>> often, if one is using an error code, the operation was probably just
>> handled as a no-op anyways.
>
> Which is another reason why error codes are bad, there's a good chance
> the programmer will ignore them, leading to undefined behavior later
> on.
>

only if the operation is likely to be critical for correct operation, in
which case one may need an exception.

many times, things are not critical, or may simply be a matter of
"Quality Of Experience" or similar, and even if the error code is
ignored, this may not actually be all that much of a problem (the error
code then being more like "did X go through successfully?" check).

sometimes, the issue may even just be something like "the amount of work
to be done ran over the time limit, so we bailed out early", which would
unlikely hinder further operation.

likewise for, say, "there were no more sound mixer channels available,
so the sound effect couldn't be played" (usually only happens if the
sound output is fairly noisy anyways, so the user is unlikely to notice
the missing sound effect).

although hardly critical to operation, code "may" care that this has
happened (say, an outer part of the rendering loop may be like "stuff is
running over the time limit, so drop the quality settings a little").


granted, these types of situations may be handled by status flags
instead (say, we have a "World" object, which may set flags in the
object indicating that some parts of the process were taking too long to
render, ...).


>>
>> one can use an exception if the situation is sufficiently critical to
>> where the caller merely carrying on as before would not be a desirable
>> outcome.
>>
>
> Except it is generally impossible for the called function to know
> whether the caller wishes to carry on afterwards or not. Hence why
> you should only return input that is useful to everyone and toss an
> exception otherwise. People who wish to carry on can install catch
> blocks. Everyone else gets precisely what they want.
>

I still say, it depends.


if they care, they may also check the return status, and if they don't
and something breaks, well, that may just be a problem which needs to be
fixed.

the other side of this coin is an uncaught exception which is prone to
blow up the application, which can be very annoying if it is due to
"silly little things which don't otherwise impact the apps' continued
functioning".

like, say, application crashes due to an uncaught
"ShadowNotDrawnTimeout" exception, because some object off in the
background didn't draw a shadow before the time limit (which, very
likely, the user would hardly even notice that it is missing).

sometimes, we want some of these sorts of conditions to just disappear
into the background noise.


hence, why a distinction can be made between things which are and are
not likely to impact continued and correct operation of the application.


>> very often, there is no reason to care, and it is better to not burden
>> the caller with the results, except when they actually care whether or
>> not the operation succeeded.
>
> Which is exactly what exceptions accomplish! The fact that my code
> continued executing at the next statement means that the called
> function succeeded. It also means I never have to worry about
> "exceptional" conditions unless I can actually provide a meaningful
> response to the condition. If I cannot, then I can pretend that it
> does not exist and go on with my lives.
>
> This results in less code, and practically never more code, for the
> caller and called function. On that basis alone, exceptions are
> superior.
>

as noted elsewhere:
it depends on if the next statement actually depends on the prior
statement having succeeded.

it it doesn't, do we need to care?


>> I disagree that stack-unwinding is the most common case.
>
> You're welcome to present evidence otherwise but you're going to be
> hard pressed to do so.
>
>> IME, no-op is the most common case, and if the error code is even
>> checked,
>
> If you're going to argue from this basis, you first have to show that
> it is correct to ignore the error codes. Tons of software ignores
> error codes even when it is not correct to do so. You're quite
> honestly adding to your already enormous burden.
>
>> it is usually done so to determine a success/failure status (so
>> that the caller logic can determine whether or not to try a different
>> option, ...).
>
> Or clean it's resources and manually unwind. Or just as likely,
> because that's so difficult to do manually, call abort() or a similar
> function to end the world.
>

"abort()" is often the worst option, from a "Quality Of Experience" POV,
as then the user has an app which simply dumps them back at the desktop
at the first sign of trouble, and even more annoying, "abort()" will
often not trap in the debugger either (unlike an uncaught exception).

often, from a QOE POV, it is better to have an application which tries
to compensate for whatever might go wrong, only "giving up" when it is
clearly the case that it can't "work as intended" (an example would be
failing to find files that it needs to start up, or failing to create
the main window or initialize the renderer or similar).


>>
>> as for "in a variable somewhere":
>> typically, this would be an object field or thread-local variable.
>>
>> an example would be, say, an object with an "obj->getError()" method or
>> similar, or a "fooGetError()" function which returns the contents of a
>> TLS variable, ...
>>
>> then it is thread-safe...
>>
>
> Both are considerable amounts of work for totally unclear benefit.
>
>> I didn't say here that it would be a global variable or similar, which
>> wouldn't be thread-safe.
>
> You described essentially the traditional C errno interface, which
> requires considerable gymnastics to achieve thread-safety.
>

traditionally, yes.


most modern C compilers essentially have errno as a macro which refers
to a thread-local variable (typically making a function call in the
process).

Ian Collins

unread,
May 29, 2012, 3:35:51 PM5/29/12
to
On 05/30/12 02:42 AM, Adam Skutt wrote:
> On May 29, 12:15 am, mike3<mike4...@yahoo.com> wrote:
>> Hi.
>>
>> I've heard about this, and wonder when is it right to use codes, and
>> when to use exceptions for reporting errors?
>
> You should almost always use exceptions. The main reason to use error
> codes in C++ would be due to compatibility concerns with C frameworks,
> or so that C-compatible wrappers can be provided for your C++ code.
>
> I've heard various stuff,
>> such as that exceptions should only be used to indicate "exceptional"
>> conditions. Yet what does that mean?
>
> It means that anything other than what the function would return if it
> completed normally, or did not fail. The question you should ask
> yourself is: "What would the function return if it simply could not
> fail?" The answer to that question (if any) is the return value.
> Anything else should almost certainly be an exception. Anything that
> will (really might) require stack unwinding to handle should also be
> an exception.

I generally agree with you but this being programming, there are always
exceptions to the rule. One would be were it is relatively expensive to
check if an operation will succeed before attempting it. A good example
of this is insertion into a set or map were both the resulting position
and whether the insertion succeeded are returned.

--
Ian Collins

Adam Skutt

unread,
May 29, 2012, 4:04:42 PM5/29/12
to
I think this is consistent with my guidelines when you take the full
API of the set and map classes into consideration. One thing I didn't
mention is that when designing class methods, one must consider the
contract and semantics of the whole class as well. This is a good
example of where one must think more carefully about what a function
is trying to do and how it will be used, though. In this case, I
would argue that inserting a duplicate is still a case where the
method cannot fail, since the requested value is still in the set
after the method returns.

Adam

Luca Risolia

unread,
May 29, 2012, 4:42:05 PM5/29/12
to
On 29/05/2012 06:15, mike3 wrote:
> if(f(&x) != SUCCESS)
> { // handle error }
> x += foo;
>
> :)
>
> Note how we can easily get LONG methods full of repeated code with
> error codes (repeated error handlers to handle similar errors at
> various function calls calling error-code-emitting functions, if one
> wants to be more graceful than simply aborting with an error to the
> next level up (which complicates what error codes a function can
> return, since it can return its own codes in addition to those
> returned by the functions below it, and those may have functions below
> THEM, and so on...).). And who likes duplicated code? eww. This seems
> a disadvantage of error codes.

As a note, an "exception" does not necessarily represents a failure. For
example, you can throw an exception to jump out of a recursive search
algorithm when the searched value is found:

void find_(Node* root, const char* str) {
if (!root)
return;
if (!strcmp(str, root->str))
throw root;
find_(root->left, str);
find_(root->right, str);
}

Node* find(Node* root, const char* str) {
try {
find_(root, str);
} catch (Node* p) {
return p;
}
throw not_found();
}

mike3

unread,
May 29, 2012, 4:51:36 PM5/29/12
to
On May 29, 6:24 am, Jorgen Grahn <grahn+n...@snipabacken.se> wrote:
> ["Followup-To:" header set to comp.lang.c++.]
<snip>
> Are you asking specifically about C++?  I will assume "yes", but I get
> a bit confused by your crossposting to comp.programming -- what's the
> proper use of exceptions varies between languages (and cultures).
>

Yes, my eye was toward C++.

<snip>
> I don't think you should try use the idea of "exceptional" conditions
> as a strict rule to apply. IIRC it was something Stroustrup came up with
> to explain how he thinks about it, but it's vague; you can debate
> what's exceptional or not for years.
>
> Some things are hard to set up general rules for.  You have to deal
> with them on a case-by-case basis.
>
<snip>

But what is the process for dealing with each case? You need some
way to reason about the cases.

> To me, it has more to do with things like:
> - are you going to take steps elsewhere to make out-of-bounds
>   requests not happen?  E.g. document "it's up to the caller
>   to stay on the map"?

What happens if we do that -- take steps elsewhere to make sure
those requests don't happen? As that just makes sense to do.

> - can it make sense not to handle the error locally?
> - would an error code be an unreasonable burden at the calling site,
>   e.g. you really want to be able to say things like
>   "get_tile(position).invert();" ?
>

The trouble with error codes, as I see it, is that they can lead to
lots
of duplicated code. If you have a function that makes several calls
to error-code-returning functions, then you need a handler around
EVERY call. If the behavior of these handlers is similar, then you
have code duplication. And duplicated code is Bad(tm). Not to
mention that all those handlers generally makes the code more
difficult to read, and can also lead to "long methods", another "bad"
thing. (e.g. if you have, say, a 10-line handler and there's 10 calls
there, then you get a 110-line Long Function. Ouch!)

> But it seems you say more or less this below!
>
<snip>

> As far as I can tell, you think about this pretty much like I do,
> except you're still trying to formalize it into some system of rules.
> Try not to do that for a while, and see how it feels.
>

Yet the approach I was using seems like a silly one (error codes
for everything but what returns a value/constructors/etc.). "Silly"
because it doesn't seem consistent or "inconsistent but in the right
way". It means you could be easily, haphazardly mixing together
operations that give error codes and that throw exceptions without
any overarching logic.

And also, I've noticed that with this "mix error codes and exceptions"
thing, that I seem to find myself adding a translation layer to
translate
between the two and having a corresponding exception object for every
error code, which makes it more difficult to add new exception/error
conditions since we have to update all those lists. Is this the wrong
way
to go about it? If so, what's a better way to?


Adam Skutt

unread,
May 29, 2012, 5:07:53 PM5/29/12
to
On May 29, 2:47 pm, BGB <cr88...@hotmail.com> wrote:
> On 5/29/2012 10:20 AM, Adam Skutt wrote:
> > On May 29, 10:45 am, BGB<cr88...@hotmail.com>  wrote:
First, I'm not sure why you felt the need to write out an example I
already rebutted. Second, I'm not sure why you think badly written C
code is justification for not using exceptions when writing C++.
Third, yes, Foo_ReadInFile should thrown an exception if it cannot
open the file or fails to read it in. Fourth, your example is
horrible even if it were idiomatic C++. It would never serve as valid
support for your position. It's too broken to be taken seriously.

> a more concrete example:
> consider we are trying to load a 3D model, but don't know in advance
> what type of 3D model we are trying to load.
>
> or, we are trying to load a graphic image, but were not given the full
> path or the file extension (it could be in one of several locations, or
> a PNG, or a JPG, or a BMP, or a TGA, ...).

You already mentioned this example (twice now!), and I already gave
the rebuttal: There's no way for the open function to know whether
this is what the caller is doing or not. The behavior of the caller
generally has no bearing on whether a function should or should not
throw an exception. This example is especially bad since it's no more
code for the caller if they wish to retry with different arguments.

>
> sometimes, the graphic loading may itself be conditional, say:
> did this texture have a normal-map image?
> we know it didn't, if none could be loaded, but otherwise it is no big
> deal (the texture is used without a normal-map).
>

So you suppress the exception in this case. BFD. That's considerably
less common then when failure to open the file is fatal; or requires
stack unwinding to prompt the user again, such as in a GUI where you
must return to the event loop and wait for new input from the user.

> an alternate scenario would be, say, if one particular branch of a
> programs' drawing code depends on shaders, but the user's system doesn't
> have shaders (say, because they have an old/crappy video card)?
>
> well, simplest option would just be to return an error (like, "hey, this
> wont work"), with the application falling back to an alternate path:
> "well, can we draw it without the shaders then?".
>
> <snip>
>
> the alternative strategy would be to always do things in the caller, like:
> if(foo->DoWeHaveShaders())
> {
>         foo->DoItWithShaders();}else
>
> {
>         foo->DoItWithoutShaders();
>
> }

No, the simplest option is to ask the card at runtime if it has
shaders and then select the code path as appropriate, using a virtual
function and all of these other wonderful tools C++ gives you for
selecting different function calls at runtime.

> I say it depends on the situation.
> and I am not saying that one doesn't use exceptions,
>
> I am not saying anything is universal rules here, but all depends on
> whatever is more convenient at the moment.

You said prefer error codes to exceptions with zero justification
presented to your opinion. When pressed, your basic rebuttal seems to
be that you're actually writing C and calling it C++ code. That is
not saying 'all depends on whatever is more convenient at the moment.'

> > Nonsense.  There's never a need to "detect[ing] 'well, that didn't
> > work', without needing to be like 'on no, stuff has gone terribly
> > wrong'."  This would be because the difference between the a retryable
> > error and a fatal error is entirely in the hands of the calling code,
> > not the called function. The response of the file open function should
> > be the same in either case, because it has no clue what is
> > appropriate.
>
> > You claim an catch block is inappropriate here, but you give no reason
> > why.  I fail to see any reason why it is inappropriate whatsoever.  It
> > doesn't even take up more space over if/else in your example.
>
> I disagree.

There's nothing to disagree about, you can modify your code above and
see it for yourself! It's not an arguable position. Exceptions serve
actual users and your made up example better than error codes.

>
> trying things and seeing what works and what doesn't is actually fairly
> common IME.

And how does the open method know that's what the calling code is
doing? How can that possibly justify the behavior of an open method?

>
> this is partly because some things are fairly common, like performing an
> operation with only partial information, and the program may have to
> probe around a little to figure out how exactly to go about doing it.
>
> >> often, if one is using an error code, the operation was probably just
> >> handled as a no-op anyways.
>
> > Which is another reason why error codes are bad, there's a good chance
> > the programmer will ignore them, leading to undefined behavior later
> > on.
>
> only if the operation is likely to be critical for correct operation, in
> which case one may need an exception.

No, I think ignoring the value of malloc even for "optional" code will
lead to undefined behavior. Ignoring a failure to open a file even
for "optional" input files can lead to undefined behavior or crashes
further down the road.

>
> many times, things are not critical, or may simply be a matter of
> "Quality Of Experience" or similar, and even if the error code is
> ignored, this may not actually be all that much of a problem (the error
> code then being more like "did X go through successfully?" check).
>
> sometimes, the issue may even just be something like "the amount of work
> to be done ran over the time limit, so we bailed out early", which would
> unlikely hinder further operation.

I have no idea what sort of situations you're imagining in your head,
but these seems like the sort of situations that someone would like to
know about.

>
> likewise for, say, "there were no more sound mixer channels available,
> so the sound effect couldn't be played" (usually only happens if the
> sound output is fairly noisy anyways, so the user is unlikely to notice
> the missing sound effect).

That's a pretty bad assumption--sound mixing is used for things other
than audio playback in games. If I'm performing professional audio
capture, then I care a lot if such an error occurs. In fact, I want
to know about it before I start my recording session, if possible.

> >> one can use an exception if the situation is sufficiently critical to
> >> where the caller merely carrying on as before would not be a desirable
> >> outcome.
>
> > Except it is generally impossible for the called function to know
> > whether the caller wishes to carry on afterwards or not.  Hence why
> > you should only return input that is useful to everyone and toss an
> > exception otherwise.  People who wish to carry on can install catch
> > blocks.  Everyone else gets precisely what they want.
>
> I still say, it depends.
>
> if they care, they may also check the return status, and if they don't
> and something breaks, well, that may just be a problem which needs to be
> fixed....

The only way to find out if the problem needs to be fixed is to check
the return code. To have any hope of correct operation, virtually
every call must now check return codes, whereas with exceptions, only
callers interested in "exceptional" behavior must do anything special.

Just because you believe error codes can routinely be ignored doesn't
actually make it true. Thus far, you haven't presented anything even
remotely compelling to suggest that it is true. Looking at the C,
POSIX, and Win32 APIs would suggest that most of the time, the error
codes simply cannot be ignored and must be examined to ensure proper
operation.

> the other side of this coin is an uncaught exception which is prone to
> blow up the application, which can be very annoying if it is due to
> "silly little things which don't otherwise impact the apps' continued
> functioning".

Which is better than crashing due to undefined behavior due to an
improperly ignored error and the resulting havok, such as data
corruption. Given the choice between the two bugs, as a user, I'd pick
the former over the latter any day.

>> Which is exactly what exceptions accomplish! The fact that my code
>> continued executing at the next statement means that the called
>> function succeeded. It also means I never have to worry about
>> "exceptional" conditions unless I can actually provide a meaningful
>> response to the condition. If I cannot, then I can pretend that it
>> does not exist and go on with my lives.

>> This results in less code, and practically never more code, for the
>> caller and called function. On that basis alone, exceptions are
>> superior.

> as noted elsewhere:
> it depends on if the next statement actually depends on the prior
> statement having succeeded.

How is this an argument for error codes in the least? Again, you're
simply not making sense at all, I have no clue how to even begin to
interpret this statement.

> >> it is usually done so to determine a success/failure status (so
> >> that the caller logic can determine whether or not to try a different
> >> option, ...).

> > Or clean it's resources and manually unwind. Or just as likely,
> > because that's so difficult to do manually, call abort() or a similar
> > function to end the world.

> "abort()" is often the worst option, from a "Quality Of Experience" POV,
> as then the user has an app which simply dumps them back at the desktop
> at the first sign of trouble, and even more annoying, "abort()" will
> often not trap in the debugger either (unlike an uncaught exception).

Yet there is tons of C code out there that does precisely that. GNU
even recommends it as their default response in several situations:
http://www.gnu.org/prep/standards/standards.html#Semantics

If you think GNU is unique in this view, then you are quite sorely
mistaken. You can go look at the source code for the various BSDs
systems and see similar behavior too.

Adam


Rui Maciel

unread,
May 29, 2012, 6:04:30 PM5/29/12
to
Luca Risolia wrote:

> As a note, an "exception" does not necessarily represents a failure. For
> example, you can throw an exception to jump out of a recursive search
> algorithm when the searched value is found:

Exceptions were developed explicitly to handle errors, as a way to to
separate error-handling code from the program logic. Although they may work
as a way to handle program logic, such as the case you pointed out, it isn't
a particularly elegant use for them.


Rui Maciel

Luca Risolia

unread,
May 29, 2012, 6:51:42 PM5/29/12
to
On 30/05/2012 00:04, Rui Maciel wrote:
> Exceptions were developed explicitly to handle errors, as a way to to
> separate error-handling code from the program logic. Although they may work
> as a way to handle program logic, such as the case you pointed out, it isn't
> a particularly elegant use for them.

What is elegant is a matter of opinion. Exceptions are not intended to
handle errors only, not according to authors like Stroustrup at least,
from whom I deliberately took one of the corner cases. Of course you
have to consider every case *cum grano salis*, I did not mean to say
that exceptions should always be used to control the program logic:

"Using exceptions as alternate returns can be an *elegant technique* for
terminating search functions – especially highly recursive search
functions such as a lookup in a tree."

from paragraph 14.5, "Exceptions that are not errors" ("The C++ Prog.
Language" 3rd ed.)

Ian Collins

unread,
May 29, 2012, 7:01:49 PM5/29/12
to
Elegant maybe, but potentially very expensive if used injudiciously.

--
Ian Collins

Luca Risolia

unread,
May 29, 2012, 7:10:28 PM5/29/12
to
On 30/05/2012 01:01, Ian Collins wrote:
> Elegant maybe, but potentially very expensive if used injudiciously.

This is true. In that particular case, there might be much space for
compiler optimizations. It would be interesting to know how it performs
compared to a traditional recursive search.

Ian Collins

unread,
May 29, 2012, 7:17:44 PM5/29/12
to
Measurement would be the only way to know and there would probably be a
(probably large) data size beyond which throwing an exception would be
faster.

--
Ian Collins

Rui Maciel

unread,
May 29, 2012, 7:23:26 PM5/29/12
to
Luca Risolia wrote:

> What is elegant is a matter of opinion. Exceptions are not intended to
> handle errors only, not according to authors like Stroustrup at least,
> from whom I deliberately took one of the corner cases. Of course you
> have to consider every case *cum grano salis*, I did not mean to say
> that exceptions should always be used to control the program logic:
>
> "Using exceptions as alternate returns can be an elegant technique for
> terminating search functions – especially highly recursive search
> functions such as a lookup in a tree."
>
> from paragraph 14.5, "Exceptions that are not errors" ("The C++ Prog.
> Language" 3rd ed.)

If you continue reading that part, you will notice that it goes as follows:

«However, such use of exceptions can easily be overused and lead to obscure
code. Whenever reasonable, one should stick to the ''exception handling is
error handling'' view. When this is done, code is clearly separated into
two categories: ordinary code and error-handling code. This makes code more
comprehensible.»

Then, if you read the chapter as a whole, you will realize that the use of
exceptions as "simply another control structure" is depicted as an oddity
instead of a reasonable or even desireable application, and this sort of use
is far from being endorsed by the author. And the reason is quite straight-
forward; employing exceptions as control structures is a bit of a hack
which, although it might appear to be a clever trick, doesn't really do
anyone any good.


Rui Maciel

Luca Risolia

unread,
May 29, 2012, 7:30:19 PM5/29/12
to
On 30/05/2012 01:23, Rui Maciel wrote:
> Luca Risolia wrote:
>
>> What is elegant is a matter of opinion. Exceptions are not intended to
>> handle errors only, not according to authors like Stroustrup at least,
>> from whom I deliberately took one of the corner cases. Of course you
>> have to consider every case *cum grano salis*, I did not mean to say
>> that exceptions should always be used to control the program logic:
>>
>> "Using exceptions as alternate returns can be an elegant technique for
>> terminating search functions – especially highly recursive search
>> functions such as a lookup in a tree."
>>
>> from paragraph 14.5, "Exceptions that are not errors" ("The C++ Prog.
>> Language" 3rd ed.)
>
> If you continue reading that part, you will notice that it goes as follows:

..which does not contradict what I said. I think we are saying the same
thing.

Nobody

unread,
May 30, 2012, 10:23:07 AM5/30/12
to
On Mon, 28 May 2012 21:15:00 -0700, mike3 wrote:

> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors? I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean?

It usually means that the condition will rarely occur in practice.

Performance-wise, exceptions are costly if the exception is actually
thrown but free if not thrown, while a status return has a constant
overhead. If the condition rarely occurs, exceptions will work out
cheaper; if the condition is common, returning a status will be cheaper.

But performance is seldom the main issue. If throwing an exception means
that typical code will just wrap the call in a try/catch block, you should
use a status return instead. If typical code will propagate errors up the
call stack, you should probably use an exception.

It's all about code structure. If exceptions make your code cleaner by
reducing the amount of error-handling code, use exceptions. If they just
mean that you replace if/else with try/catch, then use a status return.

BGB

unread,
May 30, 2012, 10:40:20 AM5/30/12
to
On 5/30/2012 9:23 AM, Nobody wrote:
> On Mon, 28 May 2012 21:15:00 -0700, mike3 wrote:
>
>> I've heard about this, and wonder when is it right to use codes, and
>> when to use exceptions for reporting errors? I've heard various stuff,
>> such as that exceptions should only be used to indicate "exceptional"
>> conditions. Yet what does that mean?
>
> It usually means that the condition will rarely occur in practice.
>
> Performance-wise, exceptions are costly if the exception is actually
> thrown but free if not thrown, while a status return has a constant
> overhead. If the condition rarely occurs, exceptions will work out
> cheaper; if the condition is common, returning a status will be cheaper.
>

pretty much.

a status code also has the advantage if the return value is used to
drive logic in the caller, such as knowing when a task has finished,
when a desired item has been found, ...


> But performance is seldom the main issue. If throwing an exception means
> that typical code will just wrap the call in a try/catch block, you should
> use a status return instead. If typical code will propagate errors up the
> call stack, you should probably use an exception.
>

agreed.

exceptions work much better for transferring control across multiple
levels of call frames.

if the handler logic is directly in the caller, then it is less convenient.


similarly, there may be the matter of seriousness:
if the situation is "serious" (as-in, could potentially compromise
correct functioning of the application), then an exception may make more
sense;
if the situation is something which could be reasonably ignored with
little or no consequence, then a status code may make more sense.


> It's all about code structure. If exceptions make your code cleaner by
> reducing the amount of error-handling code, use exceptions. If they just
> mean that you replace if/else with try/catch, then use a status return.
>

yep.

this is often what would happen in many cases, using a try/catch as a
slightly longer, and slower, alternative to an if/else block.

BGB

unread,
May 30, 2012, 10:54:29 AM5/30/12
to
On 5/29/2012 4:07 PM, Adam Skutt wrote:
> On May 29, 2:47 pm, BGB<cr88...@hotmail.com> wrote:
>> On 5/29/2012 10:20 AM, Adam Skutt wrote:
>>> On May 29, 10:45 am, BGB<cr88...@hotmail.com> wrote:
>>>> if you need to unwind the stack either way, then an exception may make
>>>> sense.
>>
>>> I fail to see how making the programmer manually do what the language
>>> does automatically is worthwhile. You're going to have to give
>>> examples, and if they're not relevant to general-case programming then
>>> please don't waste anyone's time.
>>

<snip rest>

I am not here to argue about nitpicking.

if the other posts in this thread are noted, the tradeoff depends on:
what one is doing in a given case;
which is more convenient in a given case.

try/catch is not always more convenient than if/else, and has tradeoffs
for when and where they might be used.


but, oh well, whatever...

relax, man.

Adam Skutt

unread,
May 30, 2012, 11:04:37 AM5/30/12
to
On May 30, 10:40 am, BGB <cr88...@hotmail.com> wrote:
> On 5/30/2012 9:23 AM, Nobody wrote:
>
> > On Mon, 28 May 2012 21:15:00 -0700, mike3 wrote:
>
> >> I've heard about this, and wonder when is it right to use codes, and
> >> when to use exceptions for reporting errors? I've heard various stuff,
> >> such as that exceptions should only be used to indicate "exceptional"
> >> conditions. Yet what does that mean?
>
> > It usually means that the condition will rarely occur in practice.
>
> > Performance-wise, exceptions are costly if the exception is actually
> > thrown but free if not thrown, while a status return has a constant
> > overhead. If the condition rarely occurs, exceptions will work out
> > cheaper; if the condition is common, returning a status will be cheaper.
>
> pretty much.
>
> a status code also has the advantage if the return value is used to
> drive logic in the caller, such as knowing when a task has finished,
> when a desired item has been found, ...
>

Or you just return the item and avoid the need for status altogether.
Success should be normally be implicit.

> > But performance is seldom the main issue. If throwing an exception means
> > that typical code will just wrap the call in a try/catch block, you should
> > use a status return instead. If typical code will propagate errors up the
> > call stack, you should probably use an exception.
>
> agreed.
>
> exceptions work much better for transferring control across multiple
> levels of call frames.
>
> if the handler logic is directly in the caller, then it is less convenient.

You've said this a whole bunch of times but never once demonstrated
how this is actually true. I can think of a few cases where it's
true, but they're all pretty contrived.

>
> similarly, there may be the matter of seriousness:
> if the situation is "serious" (as-in, could potentially compromise
> correct functioning of the application), then an exception may make more
> sense;
> if the situation is something which could be reasonably ignored with
> little or no consequence, then a status code may make more sense.
>

As I've explained to you before, it's normally impossible for the
function issuing the error to tell the difference between these two
situations. Again, you've never once demonstrated how to apply this
reasoning to writing correct, usable code.

Adam

Adam Skutt

unread,
May 30, 2012, 11:22:08 AM5/30/12
to
On May 30, 10:23 am, Nobody <nob...@nowhere.com> wrote:
> On Mon, 28 May 2012 21:15:00 -0700, mike3 wrote:
> > I've heard about this, and wonder when is it right to use codes, and
> > when to use exceptions for reporting errors? I've heard various stuff,
> > such as that exceptions should only be used to indicate "exceptional"
> > conditions. Yet what does that mean?
>
> It usually means that the condition will rarely occur in practice.

I don't like this definition, personally. Yes, it is true that the
sort of events that typically cause exceptions are rare. However,
that fact doesn't do us much good when actually designing software.

> But performance is seldom the main issue. If throwing an exception means
> that typical code will just wrap the call in a try/catch block, you should
> use a status return instead.

No, what you should do is return an actual useful value to the
caller. It is enormously difficult for a function writer to
accurately predict where and how any given "exceptional" condition
will be handled, so this line of reasoning is rather dubious at best.
You're welcome to provide an example, though.

> It's all about code structure. If exceptions make your code cleaner by
> reducing the amount of error-handling code, use exceptions. If they just
> mean that you replace if/else with try/catch, then use a status return.

If you are replacing if/else with try/catch I'd likely argue that your
C++ code was most likely designed wrong in the first place.

Adam

Rui Maciel

unread,
May 30, 2012, 12:50:23 PM5/30/12
to
Luca Risolia wrote:

> ..which does not contradict what I said. I think we are saying the same
> thing.

I was pointing out that it is bad form to try to shoe-horn exceptions as
control structures, and therefore it isn't a good idea to depict this sort
of use as reasonable or acceptable, let alone elegant. As a control
structure, exceptions are like a rube goldberg machine, and it isn't a good
idea to advertise rube goldberg machines as something other than
entertaining gimicks. They may be cleverly built, they may work, but there
are plenty of alternatives which are far simpler, efficient and easier to
maintain.


Rui Maciel

BGB

unread,
May 30, 2012, 1:01:04 PM5/30/12
to
On 5/30/2012 10:04 AM, Adam Skutt wrote:
> On May 30, 10:40 am, BGB<cr88...@hotmail.com> wrote:
>> On 5/30/2012 9:23 AM, Nobody wrote:
>>
>>> On Mon, 28 May 2012 21:15:00 -0700, mike3 wrote:
>>
>>>> I've heard about this, and wonder when is it right to use codes, and
>>>> when to use exceptions for reporting errors? I've heard various stuff,
>>>> such as that exceptions should only be used to indicate "exceptional"
>>>> conditions. Yet what does that mean?
>>
>>> It usually means that the condition will rarely occur in practice.
>>
>>> Performance-wise, exceptions are costly if the exception is actually
>>> thrown but free if not thrown, while a status return has a constant
>>> overhead. If the condition rarely occurs, exceptions will work out
>>> cheaper; if the condition is common, returning a status will be cheaper.
>>
>> pretty much.
>>
>> a status code also has the advantage if the return value is used to
>> drive logic in the caller, such as knowing when a task has finished,
>> when a desired item has been found, ...
>>
>
> Or you just return the item and avoid the need for status altogether.
> Success should be normally be implicit.
>

only if one knows that the function will almost always succeed (IOW:
succeeding is part of its "definition of operation").

if it may also fail as part of its normal/expected operation, then it no
longer is so clear cut.


succeeding/failing need not be the same as an error/non-error condition,
but may be due to other factors (such as an item not already being in a
list or hash-table and needing to be created, ...).

not all status codes indicate errors as well, and there may actually be
successful status codes as well (traditionally these are distinguished
by sign, where <0 means failure, and >=0 means success).


>>> But performance is seldom the main issue. If throwing an exception means
>>> that typical code will just wrap the call in a try/catch block, you should
>>> use a status return instead. If typical code will propagate errors up the
>>> call stack, you should probably use an exception.
>>
>> agreed.
>>
>> exceptions work much better for transferring control across multiple
>> levels of call frames.
>>
>> if the handler logic is directly in the caller, then it is less convenient.
>
> You've said this a whole bunch of times but never once demonstrated
> how this is actually true. I can think of a few cases where it's
> true, but they're all pretty contrived.
>

I make heavy use of code driven by "predicate functions" (functions or
methods which return a boolean value to indicate status), which are
arguably the same sort of thing as what you are arguing against.

it is all a fairly pointless and nit-picky argument at this point.



>>
>> similarly, there may be the matter of seriousness:
>> if the situation is "serious" (as-in, could potentially compromise
>> correct functioning of the application), then an exception may make more
>> sense;
>> if the situation is something which could be reasonably ignored with
>> little or no consequence, then a status code may make more sense.
>>
>
> As I've explained to you before, it's normally impossible for the
> function issuing the error to tell the difference between these two
> situations. Again, you've never once demonstrated how to apply this
> reasoning to writing correct, usable code.
>

usually a person writing an application will know what the code in the
thing is going to be doing, as well as the consequences of a given
operation succeeding or failing.

usually it is also "fairly obvious" from what the function is going to
be doing as well.


now, I am not opposing using exceptions here, by any means, as there are
many cases where they do make sense (namely, cases where the situation
*actually is* unexpected or abnormal).

for example:
running out of memory, or detecting a problem with the heap, is
something a bit more worthy of an exception.

Adam Skutt

unread,
May 30, 2012, 1:48:10 PM5/30/12
to
On May 30, 1:01 pm, BGB <cr88...@hotmail.com> wrote:
> On 5/30/2012 10:04 AM, Adam Skutt wrote:
> > On May 30, 10:40 am, BGB<cr88...@hotmail.com>  wrote:
> >> a status code also has the advantage if the return value is used to
> >> drive logic in the caller, such as knowing when a task has finished,
> >> when a desired item has been found, ...
>
> > Or you just return the item and avoid the need for status altogether.
> > Success should be normally be implicit.
>
> only if one knows that the function will almost always succeed (IOW:
> succeeding is part of its "definition of operation").
>
> if it may also fail as part of its normal/expected operation, then it no
> longer is so clear cut.

Nonsense. Trivial example: opening a file is an operation where it is
impossible to know whether success is possible until the operation is
attempted. Yet, opening a file should throw an exception if it fails
because there's no reasonable expectation that the caller can handle
the failure--there's no reasonable expectation that the program can
handle the failure at all.

The question is whether people want to write as if the function almost
always succeed, which is overwhelmingly the case. We go through great
length to create these abstractions all the time. Exceptions are just
one example of many.

> succeeding/failing need not be the same as an error/non-error condition,
> but may be due to other factors (such as an item not already being in a
> list or hash-table and needing to be created, ...).

Huh? This is literal nonsense.

> not all status codes indicate errors as well, and there may actually be
> successful status codes as well (traditionally these are distinguished
> by sign, where <0 means failure, and >=0 means success).

Yes, and are traditionally used where returning the desired value is
impossible/difficult or the error handling semantics mandate a
successful status code. They have very little value in idiomatic C++.

> I make heavy use of code driven by "predicate functions" (functions or
> methods which return a boolean value to indicate status), which are
> arguably the same sort of thing as what you are arguing against.
>

Without context, how am I supposed to know?

> it is all a fairly pointless and nit-picky argument at this point.

Hardly. Error handling is pretty fundamental to how one designs and
writes code. Calling something "pointless" and "nit-picky" just
because you lack any reasonable support for your position is pretty
childish behavior on your part, though, especially when you choose to
continue the discussion!

>
> usually a person writing an application will know what the code in the
> thing is going to be doing, as well as the consequences of a given
> operation succeeding or failing.

No. If I write a library to parse JPEG files, I have no clue what the
applications that use my library will do with my code (beyond parse
JPEG files).

Even if the code isn't mean to be shared between multiple
applications, I may have different error handling in different parts
of the application. Failing to open a configuration file may be
fatal; while failing to open a file specified by the user allows the
operation to be retried, /if a user exists/. Terminating the program
if a system call is interrupted may be appropriate if the program is
run on the console; it may not be appropriate if the program is run as
a service or GUI application.

As a result, the file opening routine must necessarily provide error
handling semantics that allow for all of these behaviors. As a
result, you pretty quickly end up in the same situation that I
describe: the routine cannot assume anything about where and how
"exceptional" situations will be handled when they occur.

> now, I am not opposing using exceptions here, by any means, as there are
> many cases where they do make sense (namely, cases where the situation
> *actually is* unexpected or abnormal).
>
> for example:
> running out of memory, or detecting a problem with the heap, is
> something a bit more worthy of an exception.

The fact you think two things that essentially cannot be handled[1]
are good examples of when exceptions are appropriate says more about
your position than anything else you've said.

Adam

[1] Or actually cannot be handled, in many cases. May the OOM killer
forever reap your leaky processes.

Jorgen Grahn

unread,
May 30, 2012, 1:50:57 PM5/30/12
to
On Tue, 2012-05-29, mike3 wrote:
> On May 29, 6:24 am, Jorgen Grahn <grahn+n...@snipabacken.se> wrote:
>> ["Followup-To:" header set to comp.lang.c++.]
> <snip>
>> Are you asking specifically about C++?  I will assume "yes", but I get
>> a bit confused by your crossposting to comp.programming -- what's the
>> proper use of exceptions varies between languages (and cultures).
>>
>
> Yes, my eye was toward C++.
>
> <snip>
>> I don't think you should try use the idea of "exceptional" conditions
>> as a strict rule to apply. IIRC it was something Stroustrup came up with
>> to explain how he thinks about it, but it's vague; you can debate
>> what's exceptional or not for years.
>>
>> Some things are hard to set up general rules for.  You have to deal
>> with them on a case-by-case basis.
>>
> <snip>
>
> But what is the process for dealing with each case? You need some
> way to reason about the cases.

The only answer I can give is "experience". I'm sorry; I know it's a
non-answer. But I haven't seen an answer yet (in books and here) which
has satisfied me.

>> To me, it has more to do with things like:
>> - are you going to take steps elsewhere to make out-of-bounds
>>   requests not happen?  E.g. document "it's up to the caller
>>   to stay on the map"?
>
> What happens if we do that -- take steps elsewhere to make sure
> those requests don't happen? As that just makes sense to do.

I meant to say that's yet another reason to use an exception, named
something like InterfaceViolationYourFault ...

>> - can it make sense not to handle the error locally?
>> - would an error code be an unreasonable burden at the calling site,
>>   e.g. you really want to be able to say things like
>>   "get_tile(position).invert();" ?
>>
>
> The trouble with error codes, as I see it, is that they can lead to
> lots
> of duplicated code. If you have a function that makes several calls
> to error-code-returning functions, then you need a handler around
> EVERY call.

Yes, we know ... or at least *I* do. I'm fighting a huge piece of C
code right now which is mostly error handling -- and not even
*appropriate* error handling, just "log a message and return error to
the caller".

...
>> But it seems you say more or less this below!
>>
> <snip>
>
>> As far as I can tell, you think about this pretty much like I do,
>> except you're still trying to formalize it into some system of rules.
>> Try not to do that for a while, and see how it feels.
>>
>
> Yet the approach I was using seems like a silly one (error codes
> for everything but what returns a value/constructors/etc.). "Silly"
> because it doesn't seem consistent or "inconsistent but in the right
> way". It means you could be easily, haphazardly mixing together
> operations that give error codes and that throw exceptions without
> any overarching logic.

Well, if you cannot find a general rule, then you still have to
make up design rules for your specific piece of software. "We'll use
exceptions for <these> things, but not for <these>." It's easier
to come up with project-specific rules: you know the people involved,
you know the environment, the robustness requirements and so on.

> And also, I've noticed that with this "mix error codes and exceptions"
> thing, that I seem to find myself adding a translation layer to
> translate
> between the two and having a corresponding exception object for every
> error code, which makes it more difficult to add new exception/error
> conditions since we have to update all those lists. Is this the wrong
> way
> to go about it? If so, what's a better way to?

That seems wrong, and I can't understand why it's happening. Error
codes (to me) should be quite isolated to specific subsystems or areas.
Like, if you do socket programming you have the API's I/O error codes
(from errno etc) at the bottom, but further up you have higher-level
exceptions like "file transfer failed", "failed to login" or "NNTP
session lost".

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Scott Lurndal

unread,
May 30, 2012, 2:04:48 PM5/30/12
to
Adam Skutt <ask...@gmail.com> writes:
>On May 30, 1:01=A0pm, BGB <cr88...@hotmail.com> wrote:
>> On 5/30/2012 10:04 AM, Adam Skutt wrote:
>> > On May 30, 10:40 am, BGB<cr88...@hotmail.com> =A0wrote:
>> >> a status code also has the advantage if the return value is used to
>> >> drive logic in the caller, such as knowing when a task has finished,
>> >> when a desired item has been found, ...
>>
>> > Or you just return the item and avoid the need for status altogether.
>> > Success should be normally be implicit.
>>
>> only if one knows that the function will almost always succeed (IOW:
>> succeeding is part of its "definition of operation").
>>
>> if it may also fail as part of its normal/expected operation, then it no
>> longer is so clear cut.
>
>Nonsense. Trivial example: opening a file is an operation where it is
>impossible to know whether success is possible until the operation is
>attempted. Yet, opening a file should throw an exception if it fails
>because there's no reasonable expectation that the caller can handle
>the failure--there's no reasonable expectation that the program can
>handle the failure at all.

I disagree. Everthing I've written can handle an open failure, in
one way or another. I don't subscribe to the windows model of death
on error.

scott

Jeff Flinn

unread,
May 30, 2012, 2:18:16 PM5/30/12
to
On 5/29/2012 12:15 AM, mike3 wrote:
> Hi.
>
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors?...

The best advice I've seen is from
http://www.boost.org/community/error_handling.html

"The simple answer is: ``whenever the semantic and performance
characteristics of exceptions are appropriate.''

An oft-cited guideline is to ask yourself the question ``is this an
exceptional (or unexpected) situation?'' This guideline has an
attractive ring to it, but is usually a mistake. The problem is that one
person's ``exceptional'' is another's ``expected'': when you really look
at the terms carefully, the distinction evaporates and you're left with
no guideline. After all, if you check for an error condition, then in
some sense you expect it to happen, or the check is wasted code.

A more appropriate question to ask is: ``do we want stack unwinding
here?'' Because actually handling an exception is likely to be
significantly slower than executing mainline code, you should also ask:
``Can I afford stack unwinding here?'' For example, a desktop
application performing a long computation might periodically check to
see whether the user had pressed a cancel button. Throwing an exception
could allow the operation to be cancelled gracefully. On the other hand,
it would probably be inappropriate to throw and handle exceptions in the
inner loop of this computation because that could have a significant
performance impact. The guideline mentioned above has a grain of truth
in it: in time critical code, throwing an exception should be the
exception, not the rule."

Jeff

Adam Skutt

unread,
May 30, 2012, 2:31:24 PM5/30/12
to
If what you said is true, then you can readily tell me what I should
do when getting ELOOP, or ENAMETOOLONG, etc. from open(2) in an
application that's run from cron job? There's no user to prompt so
the only recourse here is termination or moving on to the next input,
if there even is a next input.

Nevermind EOVERFLOW, where your only solution is termination since the
application must be recompiled.

Plus, I seriously doubt your applications has sensible and correct
handling of ENFILE or ENOMEM (if you even get to see it). Even if
they do, it's irrelevant anyway (twice over). UNIX syscalls contain
all sorts of error codes that you will either a) never practically see
b) won't be able to do anything about them if you do see them.

> I don't subscribe to the windows model of death
> on error.

The Windows model is no such thing. Even if it were, it doesn't
change the fact that many applications are run in contexts where they
have no ability to correct invalid input: they simply must reject it.
Termination is a perfectly cromulent way to reject invalid input for
many applications in these situations.

Even in contexts where the program could correct invalid input, it
seems stupid to add a input loop to mv(1), ln(1), etc. just because
the user typed in the wrong file name. The shell already has a
command loop, so why bother?

Adam

Ian Collins

unread,
May 30, 2012, 3:24:53 PM5/30/12
to
I doubt anyone would disagree about that.

One key driver is how close to the source of the error can it be
handled. For example code that expects a configuration file to be
present but can supply defaults if it is missing shouldn't use
exceptions. If there isn't a plan B, it should.

--
Ian Collins

Scott Lurndal

unread,
May 30, 2012, 3:25:48 PM5/30/12
to
Adam Skutt <ask...@gmail.com> writes:
>On May 30, 2:04=A0pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
>> Adam Skutt <ask...@gmail.com> writes:
>> >On May 30, 1:01=3DA0pm, BGB <cr88...@hotmail.com> wrote:
>> >> On 5/30/2012 10:04 AM, Adam Skutt wrote:
>> >> > On May 30, 10:40 am, BGB<cr88...@hotmail.com> =3DA0wrote:
>> >> >> a status code also has the advantage if the return value is used to
>> >> >> drive logic in the caller, such as knowing when a task has finished=
>,
>> >> >> when a desired item has been found, ...
>>
>> >> > Or you just return the item and avoid the need for status altogether=
>.
>> >> > Success should be normally be implicit.
>>
>> >> only if one knows that the function will almost always succeed (IOW:
>> >> succeeding is part of its "definition of operation").
>>
>> >> if it may also fail as part of its normal/expected operation, then it =
>no
>> >> longer is so clear cut.
>>
>> >Nonsense. Trivial example: opening a file is an operation where it is
>> >impossible to know whether success is possible until the operation is
>> >attempted. =A0Yet, opening a file should throw an exception if it fails
>> >because there's no reasonable expectation that the caller can handle
>> >the failure--there's no reasonable expectation that the program can
>> >handle the failure at all.
>>
>> I disagree. =A0 Everthing I've written can handle an open failure, in
>> one way or another.
>
>If what you said is true, then you can readily tell me what I should
>do when getting ELOOP, or ENAMETOOLONG, etc. from open(2) in an
>application that's run from cron job? There's no user to prompt so
>the only recourse here is termination or moving on to the next input,
>if there even is a next input.

That entirely depends on the application and the purpose of the
file being opened. Say the file is a i18n message catalog; the
application can simply fall back to the built-in non-i18 messages.

ELOOP and ENAMETOOLONG are almost always development errors or stupid
administrator errrors, not run-time errors, but they can
be safely lumped into the same category as ENOENT for 99.99% of
all applications.

There are almost always recovery mechanisms.

>
>Nevermind EOVERFLOW, where your only solution is termination since the
>application must be recompiled.

Not necessarily. One could, if one really needed to open a large
file and wasn't running on a 64-bit OS or with _LARGE_FILE support
(I was on the LFS committee, btw), use system(3) with dd(1) to
subdivide the file and process the pieces.

I'd consider EOVERFLOW as another example of a development-time error
that can be triggered at run-time only with invalid input (as defined
by the application). And again, it can be often treated the same
as ENOENT.


>
>Plus, I seriously doubt your applications has sensible and correct
>handling of ENFILE or ENOMEM (if you even get to see it). Even if

My applications don't leak file descriptors, so ENFILE isn't an issue.

ENOMEM, sleep and try again. After some number of attempts, give up.


>they do, it's irrelevant anyway (twice over). UNIX syscalls contain
>all sorts of error codes that you will either a) never practically see
>b) won't be able to do anything about them if you do see them.

You are being silly if you think that each possible errno return value
from a system call or library function needs to be handled separately. In
the majority of the cases, they can be simply considered to be "ENOENT"
from the standpoint of error recovery in the application.


>The Windows model is no such thing. Even if it were, it doesn't
>change the fact that many applications are run in contexts where they
>have no ability to correct invalid input: they simply must reject it.
>Termination is a perfectly cromulent way to reject invalid input for
>many applications in these situations.

In the server-side applications that I've worked with termination
is never an option. Invalid input is always screened first, and
can only reach the server application if some code flaw exists.

But then I've always been in environments where fault-tolerance
is a goal, and is assisted by hardware and software (e.g. mainframes,
massively-parallel multicomputers, supercomputers).

>
>Even in contexts where the program could correct invalid input, it
>seems stupid to add a input loop to mv(1), ln(1), etc. just because
>the user typed in the wrong file name. The shell already has a
>command loop, so why bother?

mv/cat/ln handle ENOENT-category errors perfectly. I would never advocate different.

I would deprecate perror, since it leads to often useless error messsages,
and require the programmer to output something intelligent instead (utilizing strerror(3)).

There is of course a substantial difference between a command-line utility and
a server-side application in terms of what is required to handle errors.

scott

Patricia Shanahan

unread,
May 30, 2012, 4:00:25 PM5/30/12
to
On 5/30/2012 11:18 AM, Jeff Flinn wrote:
...
> A more appropriate question to ask is: ``do we want stack unwinding
> here?'' Because actually handling an exception is likely to be
> significantly slower than executing mainline code, you should also ask:
> ``Can I afford stack unwinding here?'' For example, a desktop
> application performing a long computation might periodically check to
> see whether the user had pressed a cancel button. Throwing an exception
> could allow the operation to be cancelled gracefully. On the other hand,
> it would probably be inappropriate to throw and handle exceptions in the
> inner loop of this computation because that could have a significant
> performance impact. The guideline mentioned above has a grain of truth
> in it: in time critical code, throwing an exception should be the
> exception, not the rule."
...

*Any* style rule or pattern has a potential for being overridden by
important performance concerns. That does not mean we should not ask
"What is good style?".

I usually prefer exceptions:

1. Exceptions leave the function result available for the natural result.

2. In many languages, exceptions encode more information more directly
than is possible with status codes.

3. Exception processing can be grouped at the end of a block of code,
with the non-exception flow left clear. Status codes tend to result in
interleaving exception handling throughout the main line flow.

Patricia

BGB

unread,
May 30, 2012, 5:20:21 PM5/30/12
to
generally agreed.

Adam Skutt

unread,
May 30, 2012, 5:53:01 PM5/30/12
to
On May 30, 3:25 pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
> Adam Skutt <ask...@gmail.com> writes:
> >On May 30, 2:04=A0pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
> >> Adam Skutt <ask...@gmail.com> writes:
>
> >> >Nonsense. Trivial example: opening a file is an operation where it is
> >> >impossible to know whether success is possible until the operation is
> >> >attempted. =A0Yet, opening a file should throw an exception if it fails
> >> >because there's no reasonable expectation that the caller can handle
> >> >the failure--there's no reasonable expectation that the program can
> >> >handle the failure at all.
>
> >> I disagree. =A0 Everthing I've written can handle an open failure, in
> >> one way or another.
>
> <snip>
>
> >Even in contexts where the program could correct invalid input, it
> >seems stupid to add a input loop to mv(1), ln(1), etc. just because
> >the user typed in the wrong file name.  The shell already has a
> >command loop, so why bother?
>
> mv/cat/ln handle ENOENT-category errors perfectly.   I would never advocate different.

Yes, by terminating. Which means you cannot disagree with what I
said!

There's no sense in responding to anything else you said if you're
going to be this blatantly dishonest.

Adam

Scott Lurndal

unread,
May 30, 2012, 7:30:04 PM5/30/12
to
Adam Skutt <ask...@gmail.com> writes:
>On May 30, 3:25=A0pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
>> Adam Skutt <ask...@gmail.com> writes:
>> >On May 30, 2:04=3DA0pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
>> >> Adam Skutt <ask...@gmail.com> writes:
>>
>> >> >Nonsense. Trivial example: opening a file is an operation where it is
>> >> >impossible to know whether success is possible until the operation is
>> >> >attempted. =3DA0Yet, opening a file should throw an exception if it f=
>ails
>> >> >because there's no reasonable expectation that the caller can handle
>> >> >the failure--there's no reasonable expectation that the program can
>> >> >handle the failure at all.
>>
>> >> I disagree. =3DA0 Everthing I've written can handle an open failure, i=
>n
>> >> one way or another.
>>
>> <snip>
>>
>> >Even in contexts where the program could correct invalid input, it
>> >seems stupid to add a input loop to mv(1), ln(1), etc. just because
>> >the user typed in the wrong file name. =A0The shell already has a
>> >command loop, so why bother?
>>
>> mv/cat/ln handle ENOENT-category errors perfectly. =A0 I would never advo=
>cate different.
>
>Yes, by terminating. Which means you cannot disagree with what I
>said!
>
>There's no sense in responding to anything else you said if you're
>going to be this blatantly dishonest.

I'm sorry if you misunderstood that "handling an error" includes termination
when appropriate. Note that "when appropriate". (and note the "one way or another"
above).

I suppose my parenthetical comment about "windows terminate on error" may have
misled you.

scott

Pavel

unread,
May 30, 2012, 10:44:56 PM5/30/12
to
mike3 wrote:
> Hi.
>
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors? I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean? I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional", but
> something like running out of memory should be. Does this mean that if
> we have a program, and we have a "parse()" function that parses a
> string input by the user, that this function should return an error
> code on parse failure, instead of throwing an exception? Yet we'll
> probably also come across places where it's good to use an exception,
> in the same program! Which means we get into _mixing error codes and
> exceptions_. And what's the best way to do that?
>
> Also, how exactly does one go about determining what is and is not
> "exceptional"? Two examples were mentioned of things exceptional and
> non-exceptional, but what about something else, like say in a game,
> where you have a grid representing a game level, and a request for a
> tile of the level is made with a coordinate that is off the map (like
> a 64x64 map and something requests a tile at (100, 100).). Would it be
> OK for the function working on the tile to throw? Or should it give an
> "out of range" error code? And as for that mixing: consider, e.g. C++
> and probably many other languages: a function has a single definite
> return type. Suppose our grid had a function that extracts an
> attribute from a cell. What to do when there's an out-of-bounds
> request? Throw exception? See, what I've currently been doing, and
> it's probably silly, is to use exceptions when our function needs to
> return a value, and error codes when it could otherwise return "void".
> This doesn't seem like a good idea. But what to do? Make every
> function return an error code, using pointers to output variables to
> store output, and only use exceptions for a rare few kinds of "system-
> related" error? Yet one can hardly deny the niceness of being able to
> say "x = f() +<foo>" (inside a "try" block, perhaps) instead of
>
> if(f(&x) != SUCCESS)
> { // handle error }
> x += foo;
>
> :)
>
> Note how we can easily get LONG methods full of repeated code with
> error codes (repeated error handlers to handle similar errors at
> various function calls calling error-code-emitting functions, if one
> wants to be more graceful than simply aborting with an error to the
> next level up (which complicates what error codes a function can
> return, since it can return its own codes in addition to those
> returned by the functions below it, and those may have functions below
> THEM, and so on...).). And who likes duplicated code? eww. This seems
> a disadvantage of error codes.
>
> Or, and this is what I've been thinking of, use exceptions for every
> error that the user does not have control over, like invalid input
> strings. Would that be OK or excessive use of exceptions? And if we
> are to mix error codes and exceptions, does this mean we should have
> the lists of codes and exceptions correspond + a translator to
> translate between the two?

I know you have already received lots of advice; but I think they omit an
important factor, namely whether you are writing a library. In my experience, I
found it quite annoying when the API of a library I use can throw. Catching all
possible exceptions after every call is even more disrupting than processing
return codes and letting them through often creates a mess with multiple error
processing policies coming from different libraries or from my application and
library or libraries it uses.

In addition, a library writer does not always know the performance requirements
of the future client code, especially if it is going to be a successful library
and calling throwing function incurs overhead.

Using "golden rule", I refrain from exposing exceptions in APIs to my libraries
and strive to make all top-level functions nothrow regardless of whether or not
I use them inside the library implementation.

HTH,
-Pavel



Nobody

unread,
May 31, 2012, 12:04:36 AM5/31/12
to
On Wed, 30 May 2012 22:44:56 -0400, Pavel wrote:

> I know you have already received lots of advice; but I think they omit an
> important factor, namely whether you are writing a library. In my
> experience, I found it quite annoying when the API of a library I use can
> throw. Catching all possible exceptions after every call is even more
> disrupting than processing return codes and letting them through often
> creates a mess with multiple error processing policies coming from
> different libraries or from my application and library or libraries it
> uses.

That's a non-issue for exceptions which should never need to be thrown
in the first place, e.g. an invalid argument value. If you don't want to
have to catch such exceptions, don't cause them to be thrown.

Even where it is an issue, any API design involves trade-offs. Having
every function return a status indication may be more efficient for code
which always handles failures directly in the caller. OTOH, it imposes a
significant burden on code which would otherwise just allow an exception
to propagate up to a higher level.

It's impossible to provide a hard-and-fast definition of which conditions
are "exceptional", particularly for a library. OTOH, it's equally
impossible to provide a hard-and-fast rule regarding the side on which to
err.

Treating any condition which might conceivably be caught in the immediate
caller as non-exceptional is likely to result in a rather inconvenient API
for the majority of code. I mean, the STL *could* have a given every
container type a "bad bit" (in the same vein as iostream) to indicate
allocation failure, but I'm rather glad it didn't.

Adam Skutt

unread,
May 31, 2012, 12:25:47 AM5/31/12
to
On May 30, 2:18 pm, Jeff Flinn <TriumphSprint2...@hotmail.com> wrote:
> On 5/29/2012 12:15 AM, mike3 wrote:
>
> > Hi.
>
> > I've heard about this, and wonder when is it right to use codes, and
> > when to use exceptions for reporting errors?...
>
> The best advice I've seen is fromhttp://www.boost.org/community/error_handling.html
>
> "The simple answer is: ``whenever the semantic and performance
> characteristics of exceptions are appropriate.''
>
>
> A more appropriate question to ask is: ``do we want stack unwinding
> here?'' Because actually handling an exception is likely to be
> significantly slower than executing mainline code, you should also ask:
> ``Can I afford stack unwinding here?'' For example, a desktop
> application performing a long computation might periodically check to
> see whether the user had pressed a cancel button. Throwing an exception
> could allow the operation to be cancelled gracefully. On the other hand,
> it would probably be inappropriate to throw and handle exceptions in the
> inner loop of this computation because that could have a significant
> performance impact. The guideline mentioned above has a grain of truth
> in it: in time critical code, throwing an exception should be the
> exception, not the rule."

Except that your guidance doesn't apply here. Modern C++ runtimes
incur no execution overhead for exception handling unless an exception
is actually thrown. Since the goal is to terminate the loop entirely,
an exception would be perfectly reasonable in principal. Where it
might unreasonable is if the exception were to be caught and then
computation resumed. However, it's pointless to assume throwing an
exception will be a problem without measuring.

Adam

Adam Skutt

unread,
May 31, 2012, 12:34:34 AM5/31/12
to
If by, "shouldn't use exceptions," you really mean, "Since the
operation cannot 'fail', there's no need to throw an exception". The
other unspoken side of the coin is that there is no reason to return a
status code, /for precisely the same reason/. The only thing the code
needs to return is the configuration data.

Adam

Adam Skutt

unread,
May 31, 2012, 12:30:42 AM5/31/12
to
On May 30, 10:44 pm, Pavel
<pauldontspamt...@removeyourself.dontspam.yahoo> wrote:
> mike3 wrote:
> > Hi.
>
> > I've heard about this, and wonder when is it right to use codes, and
> > when to use exceptions for reporting errors? I've heard various stuff,
> > such as that exceptions should only be used to indicate "exceptional"
> > conditions. Yet what does that mean? I've heard that, e.g. a user
> > inputting invalid input should not be considered "exceptional", but
> > something like running out of memory should be. Does this mean that if
> > we have a program, and we have a "parse()" function that parses a
> > string input by the user, that this function should return an error
> > code on parse failure, instead of throwing an exception? Yet we'll
> > probably also come across places where it's good to use an exception,
> > in the same program! Which means we get into _mixing error codes and
> > exceptions_. And what's the best way to do that?
>
> I know you have already received lots of advice; but I think they omit an
> important factor, namely whether you are writing a library. In my experience, I
> found it quite annoying when the API of a library I use can throw. Catching all
> possible exceptions after every call is even more disrupting than processing
> return codes and letting them through often creates a mess with multiple error
> processing policies coming from different libraries or from my application and
> library or libraries it uses.

Exceptions: you are doing them wrong. You should only catch the
exceptions you are interested in, and in general, I've rarely (ever?)
needed to catch more than one class at a time. In fact, I'd generally
assume (in C++) that needing to catch more is indicative of a design
problem.

>
> In addition, a library writer does not always know the performance requirements
> of the future client code, especially if it is going to be a successful library
> and calling throwing function incurs overhead.

It's senseless to cater to such senseless micro-optimizations unless
you must. Modern C++ implementations don't incur execution overhead
unless an exception is actually tossed. I assume you don't use
libraries that use virtual functions as well because of the same
potential problem?

>
> Using "golden rule", I refrain from exposing exceptions in APIs to my libraries
> and strive to make all top-level functions nothrow regardless of whether or not
> I use them inside the library implementation.

I have to imagine either your libraries are therefore very difficult
to use idiomatically or aren't actually nothrow safe.

Adam

nick_keigh...@hotmail.com

unread,
May 31, 2012, 3:34:09 AM5/31/12
to
On Thursday, May 31, 2012 3:44:56 AM UTC+1, Pavel wrote:
> mike3 wrote:

> > I've heard about this, and wonder when is it right to use codes, and
> > when to use exceptions for reporting errors?

<snip>

> [...] an important factor [is] whether you are writing a library.
> In my experience, I found it quite annoying when the API of a
> library I use can throw.

when i've written a library I've quite liked the idea that "at least the buggers (clients) can't ignore these errors!". Well up until I found code liberally sprinkled with

catch (...)
{ /* ignore */ }

:-(

> Catching all possible exceptions after
> every call is even more disrupting than processing return codes

a well written library shouldn't be returning lots of different exceptions- and it should docuemnt the ones it does.

> and letting them through often creates a mess with multiple error
> processing policies coming from different libraries or from my
> application and library or libraries it uses.

ah. I was going argue that should put less catchs in and write exception safe code. I haven't found the problem you describe. perhaps i haven't used a sufficiently rich mix of incompatible libraries.

<snip>

nick_keigh...@hotmail.com

unread,
May 31, 2012, 3:50:23 AM5/31/12
to
On Thursday, May 31, 2012 5:30:42 AM UTC+1, Adam Skutt wrote:

<snip>

> Exceptions: you are doing them wrong. You should only catch the
> exceptions you are interested in, and in general, I've rarely (ever?)
> needed to catch more than one class at a time. In fact, I'd generally
> assume (in C++) that needing to catch more is indicative of a design
> problem.

oh? so the application I did maintenance that had 12 different (no inheritance relationship) exception classes had design issues?
:-)

mike3

unread,
May 31, 2012, 4:52:40 PM5/31/12
to
On May 29, 1:08 am, Marcel Müller <news.5.ma...@spamgourmet.com>
wrote:
<snip>
> > Would that be OK or excessive use of exceptions? And if we
> > are to mix error codes and exceptions, does this mean we should have
> > the lists of codes and exceptions correspond + a translator to
> > translate between the two?
>
> Converting an error code into an exception might be a good idea. But the
> other way around is most likely not.
>
> And another rule of thumb: the number of exceptions thrown during the
> processing of a complete request should be finite. I.e. it must not
> scale with the amount of data processed.
>
> Marcel

So does this mean we should have an exception class defined for every
error code, so we can do that "conversion"?

Ian Collins

unread,
May 31, 2012, 5:08:21 PM5/31/12
to
That really depends what you intend to do when you catch one. I tend to
use an exception type for a family of error codes and include the actual
code in there. Most of my simple applications just catch the base
exception (std::runtime_error), send the result of what() to cerr and exit.

If the application can recover from a specific type of exception, I'll
catch those a perform whatever recovery or reporting is required.

--
Ian Collins
Message has been deleted

mike3

unread,
Jun 1, 2012, 1:32:32 AM6/1/12
to
On May 31, 3:08 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 06/ 1/12 08:52 AM, mike3 wrote:
<snip>
> > So does this mean we should have an exception class defined for every
> > error code, so we can do that "conversion"?
>
> That really depends what you intend to do when you catch one. I tend to
> use an exception type for a family of error codes and include the actual
> code in there. Most of my simple applications just catch the base
> exception (std::runtime_error), send the result of what() to cerr and exit.
>
> If the application can recover from a specific type of exception, I'll
> catch those a perform whatever recovery or reporting is required.
>

I.e. don't make exception classes for every error code but make them
for
a family of error codes?

nick_keigh...@hotmail.com

unread,
Jun 1, 2012, 3:35:05 AM6/1/12
to
On Friday, June 1, 2012 6:32:32 AM UTC+1, mike3 wrote:
> On May 31, 3:08 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> > On 06/ 1/12 08:52 AM, mike3 wrote:

> > > So does this mean we should have an exception class defined for every
> > > error code, so we can do that "conversion"?
> >
> > That really depends what you intend to do when you catch one. I tend to
> > use an exception type for a family of error codes and include the actual
> > code in there. Most of my simple applications just catch the base
> > exception (std::runtime_error), send the result of what() to cerr and exit.
> >
> > If the application can recover from a specific type of exception, I'll
> > catch those a perform whatever recovery or reporting is required.

I tend to do that too. I only define my own exception types if I want special handling or it's getting messy to pack all the information into a what() string.

> I.e. don't make exception classes for every error code but make them
> for a family of error codes?

these are rules of thumb rather than hard rules. I try to derive everyting from std::exception (or rather std::runtime_error which itself derives from std::exception). That way at the top of the program you can catch and report any exception.

Lots of catch(...)s are usually a sign that someone doesn't want to do proper exception handling.

Unless your program is enourmous I'd suggest starting with throwing runtime_error.

Pavel

unread,
Jun 1, 2012, 9:44:08 PM6/1/12
to
Stefan Ram wrote:
> Pavel<pauldont...@removeyourself.dontspam.yahoo> writes:
>> I know you have already received lots of advice; but I think they omit an
>> important factor, namely whether you are writing a library. In my experience, I
>> found it quite annoying when the API of a library I use can throw.
>
> And that leads to an answer to the OP's question: When in Rome do as the
> Romans do!
That's what I always profess. With exceptions, however, it might be unclear
where's Rome and where's Athens. Just a quick example off the top of my head:

When using STL, use std::exception hierarchy.
When using WFC, use System::Exception.
When using Qt, use return codes, but for passing errors between threads, inherit
your exceptions from QtConcurrent::Exception

I believe WFC, Qt and many recent implementations of STL all are high-quality,
mostly well-designed library; the first two are also immense in coverage. More
often than not it's not an option not to use them (or other libraries pertinent
to your application's domain).

Where is Rome?

When you write your own library that will most often used with WFC, often with
Qt and always with some STL -- how shall you expose your errors?

When you write your own library that uses WFC -- and of course STL how shall you
expose your library's errors and where should you catch std::exception (which
are fortunately rare) and guys from System::Exception hierarchy (which are much
more often)?

When you write an application that uses all 3 or even only two libraries -- what
errors shall you use inside your application? Many large application require
particular processing of particular error conditions (error logs, alarms,
interfaces to enterprise event handling systems, what's not) -- are you going to
proliferate these exceptions? Usually, you don't. The benefits of uniform error
processing aside, why will you want to make more parts of your code dependent on
the libraries only because their exceptions may penetrate them and the errors
are need to be processed there? What if you need to replace such a big library
with another monster (e.g. to port your library). How are you going to tear
these dependencies out?

If you are a responsible designer, you will provide your own error processing
layer and you will have to meticulously catch and either process or crack and
refactor all errors before letting them further in a thin layer wrapping the
library calls your application uses. The code to capture error codes is simpler,
shorter and faster than that needed to capture exceptions.

As a free bonus, you (or your user if you are the library writer) can always
make a choice between writing throw and nothrow functions at no coding cost.

On top of this, following the code that only calls nothrow methods is much
easier which increases the programmer's productivity. You know, programmers of
successful real-life applications and libraries (which is equivalent to saying
"applications and libraries of significant size") have to spend more time on
reading and understanding code of others than on writing their own code.

Do your math yourself. I did mine many years ago and have never had a reason to
be sorry of this my application of golden rule.

> When in a programming language do as the standard library does!
> Look at the standard library and observe what means it uses to signal
> the status of attempts, and then use these means!
>
> In C++, »standard library« here does not mean that part inherited from
> C, but more that part written specifically for C++.
>

-Pavel

Alf P. Steinbach

unread,
Jun 2, 2012, 2:39:14 AM6/2/12
to
On 29.05.2012 06:15, mike3 wrote:
> Hi.
>
> I've heard about this [Error codes vs. exceptions], and wonder when is it
> right to use codes, and when to use exceptions for reporting errors?

Use whatever's more clear and practical in any given case.

And note that "codes" include the case of zero information about what
failed, where there's only one success indicating code (like boolean
"true") and one failure indicating code (like boolean "false")...

Also note that there are many other techniques for handling failures
that occur in a function f:

* let f return a possibly empty result
e.g. check out Barton/Nackman "Fallible" and Boost "optional"


* let f call an error handling routine, that's possibly configurable
a great many libraries do this

* let f terminate the program
a bit harsh, but e.g. a JPEG library used by ImageMagick did this

* let f involve the user and try to fix the problem
this was used in Windows for missing removable media, missing
DLLs and so on, with a box that like DOS did earlier said "abort,
ignore, retry" (or the like)

* let f simply have undefined behavior
may sound pretty stupid but is used by e.g. the C++ standard library
for functions where failures only are caused by failed preconditions

Regardless, you have the option of letting f log the incident, or not.

But generally, e.g. when I'm going to call a C library function or
Windows API function that (as they typically do) has some ad hoc fault
indication + some error code scheme, then I usually wrap it in a
function or expression that throws a C++ exception. That's generally
more convenient even for local handling of the failure. And one main
reason is that it encapsulates and gets rid of all the myriad ad hoc
schemes for checking whether the function failed and for responding to
it -- it's a standardization and simplification.

As an example,

<code>
// `errno` may be an expression macro, so it cannot (portably) be
qualified with "::".
int stdErrno() { return errno; }
void clearStdErrno() { errno = 0; }

bool hopefully( bool const condition ) { return condition; }
bool throwX( string const& s ) { throw runtime_error( s ); }


long longFrom(
char const spec[],
int const radix = 0,
bool const acceptTrailingChars = false
)
{
char* pEndOfScan = 0; // The unsafe type is required by `strtol`.

clearStdErrno();
long const result = strtol( spec, &pEndOfScan, radix );
string const failureDescription = 0?string()
: pEndOfScan == spec?
"longFrom failed: the number spec was not accepted by
strtol()."
: stdErrno() == ERANGE?
"longFrom failed: the specified number value is too large
for strtol()."
: stdErrno() != 0?
S() << "longFrom failed: strtol() failed, errno = " <<
stdErrno() << "."
: *pEndOfScan != '\0' && !acceptTrailingChars?
"longFrom failed: extraneous character(s) after valid
number spec."
:
"";
hopefully( failureDescription.length() == 0 )
|| throwX( failureDescription );
return result;
}
</code>


As shown by the various exception messages there are (at least) 4 ways
that "strtol" can fail.

I would speculate that in many programs using the "strtol" function
directly, not all failure paths are checked -- but the wrapper
replaces the sequence of four ad hoc checks with simple standard C++
exception handling. Of course, with a C++11 conforming compiler there's
little need to call "strtol" because in C++11 iostreams do that for you
(C++03 instead used the "scanf" family, with possible Undefined
Behavior). But I think it illustrates the case for wrapping in C++.

So, C = preference for codes, error handlers functions etc., and C++ =
preference for exceptions. But in some cases, as with e.g. calls across
binary module boundaries, you can't assume C++ exception support. Then
you have to design for the code to be callable as C, i.e. no exceptions.

All that said, I'm primarily responding because I'm really curious about
where this great need for MECHANICAL RULES comes from?

If programming could be reduced to mechanical rules, if that was a good
idea, then, u know, it could be automated, and then you would not have
this problem of finding the rules because you wouldn't be programming:
it would be done by machine... So, instead of seeking mechanical rules
to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
failure handling. Then apply INTELLIGENCE and understanding of concrete
situations that you face, and just strive to Keep Things Simple. ;-)


Cheers & hth.,

- Alf

BGB

unread,
Jun 2, 2012, 5:31:26 PM6/2/12
to
On 6/2/2012 1:39 AM, Alf P. Steinbach wrote:
> On 29.05.2012 06:15, mike3 wrote:
>> Hi.
>>
>> I've heard about this [Error codes vs. exceptions], and wonder when is it
>> right to use codes, and when to use exceptions for reporting errors?
>
> Use whatever's more clear and practical in any given case.
>

generally agreed.


> And note that "codes" include the case of zero information about what
> failed, where there's only one success indicating code (like boolean
> "true") and one failure indicating code (like boolean "false")...
>
> Also note that there are many other techniques for handling failures
> that occur in a function f:
>
> * let f return a possibly empty result
> e.g. check out Barton/Nackman "Fallible" and Boost "optional"
>

possibly.


>
> * let f call an error handling routine, that's possibly configurable
> a great many libraries do this
>

seems good.


> * let f terminate the program
> a bit harsh, but e.g. a JPEG library used by ImageMagick did this
>

I personally consider this to be an unreasonable strategy in the general
case, since then a "reasonable" or even "trivial" issue may cause the
application to die, possibly without any way to recover short of the
application not using the library in the first place.


I have ended up dropping libraries in the past for pulling this sort of
thing (well, among other things).

like:
call library to load something from a file;
file fails to open;
library calls "abort()".

this is along with the annoyance of libraries which can only work with
files, but the data in question (in the application) is held in buffers
or similar.



> * let f involve the user and try to fix the problem
> this was used in Windows for missing removable media, missing
> DLLs and so on, with a box that like DOS did earlier said "abort,
> ignore, retry" (or the like)
>

in most cases, this probably shouldn't be done in library code (but
should probably be left up to the application).

it was an extra annoyance a while back trying to figure out how to go
about making Windows not throw up a dialog box whenever a
"LoadLibrary()" call failed to work (Windows just assumed that a
"LoadLibrary()" call failing was a serious problem, rather than, say,
this call being used to check for an optional component).

luckily, there was an option to disable said dialog.



> * let f simply have undefined behavior
> may sound pretty stupid but is used by e.g. the C++ standard library
> for functions where failures only are caused by failed preconditions
>

possibly, in this case.

I generally prefer code which doesn't just randomly blow up though, if
possible (usually, about the only real cases it is a good idea to skip
over basic "sanity checks" is in cases of "potentially performance
critical" code).


fairly common in my case is that, if the code for whatever reason can't
do what is requested, it will function as a no-op and indicate that it
has failed (and sometimes log the error if likely relevant).

in many cases, "assert" or similar can also be useful (in the case of
"clearly wrong behavior which should never occur during operation", for
example a required parameter being NULL, ...).

for example, if a required parameter is NULL or argument values are
invalid, very likely the caller has done something wrong, and it is
likely a good idea to trap into the debugger.

this isn't IMO a good strategy for "general issues" though, but more for
cases where "the caller has clearly done something wrong" or similar.


> Regardless, you have the option of letting f log the incident, or not.
>

I actually do a fair amount of logging.

typically my apps will spit out a fair amount of information to logs as
part of their start-up process, and typically this will consist largely
of debugging-related messages.

this is fairly useful as, sadly, not everything can be easily tracked
down in a debugger (very often the case with bugs which result from
interactions between components, where often much of the effort may come
down to trying to track down just where exactly the bug actually is or
the state of the system in cases where it manifests).


> But generally, e.g. when I'm going to call a C library function or
> Windows API function that (as they typically do) has some ad hoc fault
> indication + some error code scheme, then I usually wrap it in a
> function or expression that throws a C++ exception. That's generally
> more convenient even for local handling of the failure. And one main
> reason is that it encapsulates and gets rid of all the myriad ad hoc
> schemes for checking whether the function failed and for responding to
> it -- it's a standardization and simplification.

yep, seems reasonable as such.


decided mostly to leave out descriptions of some of the hassles of
trying to use exception handling in C code via hand-rolled mechanisms
(it can be done, but isn't very pretty), or dealing with cross-language
error-handling (extra fun when the project is split between 3 or more
languages).


< snip, strtol example >

>
> As shown by the various exception messages there are (at least) 4 ways
> that "strtol" can fail.
>
> I would speculate that in many programs using the "strtol" function
> directly, not all failure paths are checked -- but the wrapper replaces
> the sequence of four ad hoc checks with simple standard C++ exception
> handling. Of course, with a C++11 conforming compiler there's little
> need to call "strtol" because in C++11 iostreams do that for you (C++03
> instead used the "scanf" family, with possible Undefined Behavior). But
> I think it illustrates the case for wrapping in C++.
>

fair enough.


> So, C = preference for codes, error handlers functions etc., and C++ =
> preference for exceptions. But in some cases, as with e.g. calls across
> binary module boundaries, you can't assume C++ exception support. Then
> you have to design for the code to be callable as C, i.e. no exceptions.
>

yep.

it is better not to require a particular language for a library interface.

sometimes optional wrapper interfaces may make sense though, such as
wrapper classes or overloaded operators, ...


> All that said, I'm primarily responding because I'm really curious about
> where this great need for MECHANICAL RULES comes from?
>
> If programming could be reduced to mechanical rules, if that was a good
> idea, then, u know, it could be automated, and then you would not have
> this problem of finding the rules because you wouldn't be programming:
> it would be done by machine... So, instead of seeking mechanical rules
> to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
> failure handling. Then apply INTELLIGENCE and understanding of concrete
> situations that you face, and just strive to Keep Things Simple. ;-)
>

I actually have little idea where it comes from, but I have seen lots of
this in a number of language groups, namely people who believe that
"language X must be used this particular way", following certain little
rules (often trivial, sometimes arcane), and also that they represent
"authority" on "what everyone using the language does and believes".


sometimes, there are good "rules of thumb", but ultimately it comes down
to whether or not the rule will be beneficial in a given situation,
rather than it being something which must always be followed (even in
situations where it doesn't make sense or would do more harm than good).

although, sometimes there are edge cases, for example, "goto":
there is a rule to never use "goto";
then again, there are some potential edge cases where it could be
useful, and it seems disagreeable to ban a feature outright;
however, for code that is not already a mess, it is very rare to
actually have much need to use a "goto" to begin with (so, it seems more
like it is a symptom of spaghetti code, rather than the cause of said
spaghetti code).


many other cases appear to be similar, with people more often focusing
more on the symptoms of a problem, rather than on the cause of the
problem. ( they see the symptoms and the cause as one and the same? )


or such...

mike3

unread,
Jun 2, 2012, 6:49:12 PM6/2/12
to
On Jun 2, 12:39 am, "Alf P. Steinbach" <alf.p.steinbach
+use...@gmail.com> wrote:
> On 29.05.2012 06:15, mike3 wrote:
<snip>
> All that said, I'm primarily responding because I'm really curious about
> where this great need for MECHANICAL RULES comes from?
>
> If programming could be reduced to mechanical rules, if that was a good
> idea, then, u know, it could be automated, and then you would not have
> this problem of finding the rules because you wouldn't be programming:
> it would be done by machine... So, instead of seeking mechanical rules
> to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
> failure handling. Then apply INTELLIGENCE and understanding of concrete
> situations that you face, and just strive to Keep Things Simple. ;-)
>

So where could I get examples of _well-written_, _well-designed_,
_smell-free_ error handling in a _non-trivial_ program?

And also, perhaps I'm not necessarily so interested in rigid rules as
to
understand better how to make "good" code.

A big problem is that I seem to find a lot of conflicting information.
Some say use exceptions, others say use codes, others say use
exceptions only when "exceptional", otherwise presumably use codes.
But codes have a number of problems of their own (see the thread
on comp.lang.c where I deal with C where there are no exceptions
and only codes). Which makes me want to use exceptions. And
indeed, some say that -- use exceptions. But then I get this thing
in my head saying "but maybe those people who say it should only
be used in 'exceptional' circumstances have a good point". And
then I'm once again confused. And then what "exceptional" means
is itself, apparently dependent on the speaker.

Would I be right to think the best thing to do here is just pick an
approach and see where it goes, don't bother worrying who's more
"right"? Is this just one of those things that simply does not *have*
a pat, objective answer, and so you have to do some picking and
choosing and seeing what happens?

And then I look at examples with other programs, and I see the
practices someone says "no" to being used! "NO" globals, there's
a global! And sometimes it's not even just one but a whole lot!
"NO" GOTOs, and oh my gosh what is that?! A GOTO!!!!! Keep
methods "under 20 lines", and then I see a lot of huge methods.
And it doesn't help when the tone I hear from the people and places
saying "no" is one of near-finality, like these things should only be
used in RARE circumstances.

Balog Pal

unread,
Jun 2, 2012, 7:08:53 PM6/2/12
to
> I've heard about this, and wonder when is it right to use codes, and
> when to use exceptions for reporting errors?

Simple guide is that you use return code if the immediate caller is supposed
to care about the failure details and act. While throw is for long-range
communication. Not surprizingly for some functions both make sense.

> I've heard various stuff,
> such as that exceptions should only be used to indicate "exceptional"
> conditions. Yet what does that mean? I've heard that, e.g. a user
> inputting invalid input should not be considered "exceptional", but
> something like running out of memory should be.

Makes sense.

> Does this mean that if
> we have a program, and we have a "parse()" function that parses a
> string input by the user, that this function should return an error
> code on parse failure, instead of throwing an exception? Yet we'll
> probably also come across places where it's good to use an exception,
> in the same program! Which means we get into _mixing error codes and
> exceptions_. And what's the best way to do that?

Look for antipatterns.

If you see abundance of try blocks, especially catch after a single call,
the function would be better off with return code.

If you see return-code-football happening, like a row of
if ( (ret = Act()) < 0)
return ret;
you'd be better off throwing, and a catch where actual handling happens.

Certainly this applies to healthy, C++-style code, where objects take care
of themselves (see RAII), and no explicit management code is needed. If you
see free/delete/close... actions in the catch blocks and after those ifs,
fix that first.

> Also, how exactly does one go about determining what is and is not
> "exceptional"?

You issue a command and expect it to succeed under normal working
conditions. I.e. I expect that there's enough memory to complete the task,
that there's enough space on FS to write, TCP connection delivers, the valid
database operation carries out, I can open the files the program created,
or are there as part of the install.

If any of those fail, it's exception.

OTOH raw input form a user/outside world can be anything, so first it must
be checked/sanitized. Failure is properly expected.

However the decision is a practical matter. you balance good-looking code
and consider runtime penalties. Don't sweat on cases where you have no clear
pick.

> Two examples were mentioned of things exceptional and
> non-exceptional, but what about something else, like say in a game,
> where you have a grid representing a game level, and a request for a
> tile of the level is made with a coordinate that is off the map (like
> a 64x64 map and something requests a tile at (100, 100).).

Depends on what is asking. If your program code that should have obey the
bounds, then it is a completely different field, that of assert() and
terminate() due to detected bug.

If it's input from outsude, then you shall gate it, and have behavior
defined in the design.

> Would it be
> OK for the function working on the tile to throw? Or should it give an
> "out of range" error code? And as for that mixing: consider, e.g. C++
> and probably many other languages: a function has a single definite
> return type. Suppose our grid had a function that extracts an
> attribute from a cell. What to do when there's an out-of-bounds
> request?

That is up to you to define. If you specify the bounds as precondition, then
you may leave the behavior undefined. (Or you may define it to something,
but it helps little outside a testing environment).

> Throw exception? See, what I've currently been doing, and
> it's probably silly, is to use exceptions when our function needs to
> return a value, and error codes when it could otherwise return "void".

Certainly the function is hosed. :) exception looks like the easy way out.
But that holds only locally. If the caller thought the bounds were okay, and
turned out wrong, who shall handle the exception and how?

OTOH you can define the function as 'best-effort', and allow blind calls.
Definig the behavior as you like, including to throw or return some default
ot NULL object. (consider a sparse matrix with unlimited size, that holds
only values for cells explicitly set, and for anything else returns 0.)

> This doesn't seem like a good idea. But what to do? Make every
> function return an error code, using pointers to output variables to
> store output, and only use exceptions for a rare few kinds of "system-
> related" error? Yet one can hardly deny the niceness of being able to
> say "x = f() + <foo>" (inside a "try" block, perhaps) instead of
>
> if(f(&x) != SUCCESS)
> { // handle error }
> x += foo;
>
> :)

Exactly. The cheese of error handling is the HANDLING part, not emitting
the error via whatever means. Concentrate on that, and the rest will be
easy.

In a normal system that use exceptions the catch stes are pretty rare, and
most functions are exception-transparent.

The function that detects a problem condition is normally clueless on what
to do, and same goes for its immediate invoker... :)

> Note how we can easily get LONG methods full of repeated code with
> error codes (repeated error handlers to handle similar errors at
> various function calls calling error-code-emitting functions, if one
> wants to be more graceful than simply aborting with an error to the
> next level up

This sounds quite fishy. You either handle the error or not -- there is
hardly place to be graceful.

> (which complicates what error codes a function can
> return, since it can return its own codes in addition to those
> returned by the functions below it, and those may have functions below
> THEM, and so on...).). And who likes duplicated code? eww. This seems
> a disadvantage of error codes.

It is.

> Or, and this is what I've been thinking of, use exceptions for every
> error that the user does not have control over, like invalid input
> strings. Would that be OK or excessive use of exceptions? And if we
> are to mix error codes and exceptions, does this mean we should have
> the lists of codes and exceptions correspond + a translator to
> translate between the two?

Why you think they shall be connected? Just use everything for its own
benefit.


Ian Collins

unread,
Jun 2, 2012, 7:17:06 PM6/2/12
to
On 06/ 3/12 10:49 AM, mike3 wrote:
> On Jun 2, 12:39 am, "Alf P. Steinbach"<alf.p.steinbach
> +use...@gmail.com> wrote:
>> On 29.05.2012 06:15, mike3 wrote:
> <snip>
>> All that said, I'm primarily responding because I'm really curious about
>> where this great need for MECHANICAL RULES comes from?
>>
>> If programming could be reduced to mechanical rules, if that was a good
>> idea, then, u know, it could be automated, and then you would not have
>> this problem of finding the rules because you wouldn't be programming:
>> it would be done by machine... So, instead of seeking mechanical rules
>> to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
>> failure handling. Then apply INTELLIGENCE and understanding of concrete
>> situations that you face, and just strive to Keep Things Simple. ;-)
>>
>
> So where could I get examples of _well-written_, _well-designed_,
> _smell-free_ error handling in a _non-trivial_ program?
>
> And also, perhaps I'm not necessarily so interested in rigid rules as
> to
> understand better how to make "good" code.
>
> A big problem is that I seem to find a lot of conflicting information.
> Some say use exceptions, others say use codes, others say use
> exceptions only when "exceptional", otherwise presumably use codes.

I don't think anyone advocates mixing styles. Pick one or the other.

> But codes have a number of problems of their own (see the thread
> on comp.lang.c where I deal with C where there are no exceptions
> and only codes).

Which is why most modern languages have exceptions.

> Which makes me want to use exceptions. And
> indeed, some say that -- use exceptions. But then I get this thing
> in my head saying "but maybe those people who say it should only
> be used in 'exceptional' circumstances have a good point". And
> then I'm once again confused. And then what "exceptional" means
> is itself, apparently dependent on the speaker.

If you go down the exceptions route, your functions will either have a
void return or return a value. Your functions will do what they are
contracted to do and throw an exception if they are unable to meet their
obligations. That may involve the option of spitting some operations
into two calls (say does item X exist and get item X). The client code
can happily call the functions and move on. The error handling is not
mixed in with the programme logic, it is collected together in exception
handler(s). If that style suits you, follow it.

If you prefer to mix error handling with programme logic, use error
codes and make sure to check them!

> Would I be right to think the best thing to do here is just pick an
> approach and see where it goes, don't bother worrying who's more
> "right"? Is this just one of those things that simply does not *have*
> a pat, objective answer, and so you have to do some picking and
> choosing and seeing what happens?

Yes, assuming a green field project. Otherwise use the "when in Rome"
approach.

> And then I look at examples with other programs, and I see the
> practices someone says "no" to being used! "NO" globals, there's
> a global! And sometimes it's not even just one but a whole lot!
> "NO" GOTOs, and oh my gosh what is that?! A GOTO!!!!! Keep
> methods "under 20 lines", and then I see a lot of huge methods.
> And it doesn't help when the tone I hear from the people and places
> saying "no" is one of near-finality, like these things should only be
> used in RARE circumstances.

Creating rules and ignoring them is a clear sign of a broken process.
If anyone were to find a goto in my code, I would be obliged to buy them
a very large quantity of beer.

--
Ian Collins

Balog Pal

unread,
Jun 2, 2012, 7:33:33 PM6/2/12
to
>> All that said, I'm primarily responding because I'm really curious about
>> where this great need for MECHANICAL RULES comes from?
>>
>> If programming could be reduced to mechanical rules, if that was a good
>> idea, then, u know, it could be automated, and then you would not have
>> this problem of finding the rules because you wouldn't be programming:
>> it would be done by machine... So, instead of seeking mechanical rules
>> to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
>> failure handling. Then apply INTELLIGENCE and understanding of concrete
>> situations that you face, and just strive to Keep Things Simple. ;-)

Yeah.
>
> So where could I get examples of _well-written_, _well-designed_,
> _smell-free_ error handling in a _non-trivial_ program?

Why would you need examples?

K-PEX-ians would likely say that any inelligent being is well capable of
telling right from wrong -- you even demonstrated it in the initial message,
so all you lack is self-confidence. ;-)

You see the noise and repetition caused by mis-application of a method. So
just think the alternatives and chose the one that has least of those
problems.

> And also, perhaps I'm not necessarily so interested in rigid rules as
> to
> understand better how to make "good" code.

Write alternatives and read them back. Ot show them for review.

And no, you can't have a general solution for the concrete problems. No
silver bullets. You must think alternatives for every particular case.

> A big problem is that I seem to find a lot of conflicting information.

Just like the three blind guys go into "contradictions" describing the
elephant...

> Some say use exceptions, others say use codes, others say use
> exceptions only when "exceptional", otherwise presumably use codes.
> But codes have a number of problems of their own (see the thread
> on comp.lang.c where I deal with C where there are no exceptions
> and only codes).

Heh, is there a point in that discussion? It should be vwell known, that you
can have only two kinds of C code: the incorrect and the unreadable.
Exactly due to the lack of sensible centralized error handling, and
auto-cleanup. So any code that actually checks the return codes (that in C
have no realistic good alternatives) will be infested with all the checks
and cleanup actions. To a level you can't see what should go on.

> Which makes me want to use exceptions. And
> indeed, some say that -- use exceptions. But then I get this thing
> in my head saying "but maybe those people who say it should only
> be used in 'exceptional' circumstances have a good point".

Did you try the 'five whys' method?

Sure they have some point. Dig out what it is, and you can decide whether it
applies to your case or not.

> And
> then I'm once again confused. And then what "exceptional" means
> is itself, apparently dependent on the speaker.

Probably more dependent on the patricular situation. The same event can be
exceptional in one program and exceptional in another.


> Would I be right to think the best thing to do here is just pick an
> approach and see where it goes, don't bother worrying who's more
> "right"?

Hell yes. ;-) The Master thought to tell the good tree by the good
fruits.

> Is this just one of those things that simply does not *have*
> a pat, objective answer, and so you have to do some picking and
> choosing and seeing what happens?

IMO the stuff for which some objective answer exists is pretty rare.

> And then I look at examples with other programs, and I see the
> practices someone says "no" to being used! "NO" globals, there's
> a global! And sometimes it's not even just one but a whole lot!
> "NO" GOTOs, and oh my gosh what is that?! A GOTO!!!!! Keep
> methods "under 20 lines", and then I see a lot of huge methods.
> And it doesn't help when the tone I hear from the people and places
> saying "no" is one of near-finality, like these things should only be
> used in RARE circumstances.

Huh. Did you ever hear people saying that any guideline is only as good as
you understand its rationale?

I met a plenty of those "NO" guys, asked the 5 whys, most started to sweat
blood right at the first, or didn;t even understand what "why" means and if
he supposed to provide some answer.

Those you san send directly to <Censored> not passing GO and not collecting
$200.

OTOH look how true mentors work. Like HS+AA with the book 'C++ Coding
Standards'. For every item it is told why it's good, why bad, what are
exceptions, and provide a deal of references to more detailed explanation.
And you will find that those references have similar quality.



Balog Pal

unread,
Jun 2, 2012, 8:00:26 PM6/2/12
to
>So does this mean we should have an exception class defined for every
>error code, so we can do that "conversion"?

Why would you use a *class* to represent a single value?

A single class OsException can very well have a member to hold the value of
errno (and another for GetLastError()) so covering all the values those
take.

Balog Pal

unread,
Jun 2, 2012, 8:27:58 PM6/2/12
to
> I know you have already received lots of advice; but I think they omit an
> important factor, namely whether you are writing a library. In my
> experience, I found it quite annoying when the API of a library I use can
> throw. Catching all possible exceptions after every call is even more
> disrupting than processing return codes and letting them through often
> creates a mess with multiple error processing policies coming from
> different libraries or from my application and library or libraries it
> uses.

A polite library that throws defines a hierarchy of exceptions and makes all
of them catch-able using a single root. And even that is supposed to be a
subclass of something likely present in the environment (std::exception,
CException if the library uses MFC, etc...) so they can be processed along
with others.

And catching exceptions after every call is hardly a good use -- catch them
collectively.


Luca Risolia

unread,
Jun 2, 2012, 10:00:04 PM6/2/12
to
On 03/06/2012 00:49, mike3 wrote:
> So where could I get examples of _well-written_, _well-designed_,
> _smell-free_ error handling in a _non-trivial_ program?

Non-trivial programs tend to be a bad source of good examples.
Examples of ideal solutions to *non-trivial problems* are in good
textbooks, So take a good one and let it be your bible for some time.

mike3

unread,
Jun 2, 2012, 11:16:31 PM6/2/12
to
On Jun 2, 5:33 pm, "Balog Pal" <p...@lib.hu> wrote:
> >> All that said, I'm primarily responding because I'm really curious about
> >> where this great need for MECHANICAL RULES comes from?
>
> >> If programming could be reduced to mechanical rules, if that was a good
> >> idea, then, u know, it could be automated, and then you would not have
> >> this problem of finding the rules because you wouldn't be programming:
> >> it would be done by machine... So, instead of seeking mechanical rules
> >> to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
> >> failure handling. Then apply INTELLIGENCE and understanding of concrete
> >> situations that you face, and just strive to Keep Things Simple. ;-)
>
> Yeah.
>
>
>
> > So where could I get examples of _well-written_, _well-designed_,
> > _smell-free_ error handling in a _non-trivial_ program?
>
> Why would you need examples?
>
> K-PEX-ians would likely say that any inelligent being is well capable of
> telling right from wrong -- you even demonstrated it in the initial message,
> so all you lack is self-confidence. ;-)
>

What are "K-PEX-ians"?

> You see the noise and repetition caused by mis-application of a method. So
> just think the alternatives and chose the one that has least of those
> problems.
>

What if one of the alternatives that looks good is something often
considered
"bad"? Like a global, or a goto?

> > And also, perhaps I'm not necessarily so interested in rigid rules as
> > to
> > understand better how to make "good" code.
>
> Write alternatives and read them back. Ot show them for review.
>

You mean write the code and then read it to yourself? Write a method,
sniff it with your own nose?

> And no, you can't have a general solution for the concrete problems. No
> silver bullets. You must think alternatives for every particular case.
>

I didn't think so. I was looking more for just what needs to be
considered.

> > A big problem is that I seem to find a lot of conflicting information.
>
> Just like the three blind guys go into "contradictions" describing the
> elephant...
>

So does this mean the positions "use only exceptions" and "mix error
codes with exceptions" and "use only error codes" are not as
contradictory as they seem?

> > Some say use exceptions, others say use codes, others say use
> > exceptions only when "exceptional", otherwise presumably use codes.
> > But codes have a number of problems of their own (see the thread
> > on comp.lang.c where I deal with C where there are no exceptions
> > and only codes).
>
> Heh, is there a point in that discussion? It should be vwell known, that you
> can have only two kinds of C code: the incorrect and the unreadable.
> Exactly due to the lack of sensible centralized error handling, and
> auto-cleanup. So any code that actually checks the return codes (that in C
> have no realistic good alternatives) will be infested with all the checks
> and cleanup actions. To a level you can't see what should go on.
>

Does this mean that C sucks?

> > Which makes me want to use exceptions. And
> > indeed, some say that -- use exceptions. But then I get this thing
> > in my head saying "but maybe those people who say it should only
> > be used in 'exceptional' circumstances have a good point".
>
> Did you try the 'five whys' method?
>
> Sure they have some point. Dig out what it is, and you can decide whether it
> applies to your case or not.
>

So then you should ask "why? why? why?" to ALL these rules -- use
only exceptions, use exceptions only when "exceptional" with error
codes
for everything else, use only error codes, never make a method more
than
X long (20 lines, one screen, etc.), never use a global, never use a
goto,
avoid singleton, etc.?
Isn't that a BIG problem if "most" fail to understand these reasons?
Does this mean I should get to work spending a lot of time memorizing
rationale? Where can I find detailed rationale for all these rules --
no long method,
no global, no goto, exceptions vs error codes, etc. so as to be able
to know
enough rationale to pass the "5 whys test"?

mike3

unread,
Jun 2, 2012, 11:16:47 PM6/2/12
to
Which ones would those be?

Adam Skutt

unread,
Jun 2, 2012, 11:58:11 PM6/2/12
to
On Jun 2, 6:49 pm, mike3 <mike4...@yahoo.com> wrote:
> On Jun 2, 12:39 am, "Alf P. Steinbach" <alf.p.steinbach
>
> +use...@gmail.com> wrote:
> > On 29.05.2012 06:15, mike3 wrote:
> <snip>
> > All that said, I'm primarily responding because I'm really curious about
> > where this great need for MECHANICAL RULES comes from?
>
> > If programming could be reduced to mechanical rules, if that was a good
> > idea, then, u know, it could be automated, and then you would not have
> > this problem of finding the rules because you wouldn't be programming:
> > it would be done by machine... So, instead of seeking mechanical rules
> > to be applied mindlessly, I suggest seeking up concrete EXAMPLES of
> > failure handling. Then apply INTELLIGENCE and understanding of concrete
> > situations that you face, and just strive to Keep Things Simple. ;-)
>
> So where could I get examples of _well-written_, _well-designed_,
> _smell-free_ error handling in a _non-trivial_ program?

Just write code that uses the STL and iostreams w/ exceptions
enabled. That gives you a pretty decent model to follow, as C++ goes.

>
> And also, perhaps I'm not necessarily so interested in rigid rules as
> to
> understand better how to make "good" code.
>
> A big problem is that I seem to find a lot of conflicting information.
> Some say use exceptions, others say use codes, others say use
> exceptions only when "exceptional", otherwise presumably use codes.

That's because some people can't get over the fact that programming C
is not the best approach to everything, especially in languages other
than C.

> But codes have a number of problems of their own (see the thread
> on comp.lang.c where I deal with C where there are no exceptions
> and only codes). Which makes me want to use exceptions. And
> indeed, some say that -- use exceptions. But then I get this thing
> in my head saying "but maybe those people who say it should only
> be used in 'exceptional' circumstances have a good point". And
> then I'm once again confused. And then what "exceptional" means
> is itself, apparently dependent on the speaker.

All that means is you shouldn't use exceptions as a value return
mechanism. You're entirely over thinking the problem. If a function
has a natural value to return, then it should return that value. If
it doesn't have a value to return and is only evaluated for side-
effects, it should return void. If the function cannot complete
whatever normal processing it was asked to do, then it should throw an
exception.

What is and isn't an exceptional condition is obvious based on the
situation at least 99/100 times, so you're wringing your hands about
nothing.

The hard part about exception handling is not deciding when to throw
(normally obvious) or what to throw (doesn't matter that much in the
grand scheme of things). The hard part is ensuring that the code you
write is safe when an exception is thrown: that it properly cleans up
after any resources it allocates and provides one of the three
exception-safety guarantees.

>
> Would I be right to think the best thing to do here is just pick an
> approach and see where it goes, don't bother worrying who's more
> "right"?

Yes, and No. Yes, because you're overthinking something that honestly
isn't that difficult all the time. No, because there is a "right"
answer here: use exceptions. The people supporting error codes in any
regard can't actually support their view, and when you take an example
and code them side-by-side, the winner is pretty apparent.


> And then I look at examples with other programs, and I see the
> practices someone says "no" to being used! "NO" globals, there's
> a global! And sometimes it's not even just one but a whole lot!
> "NO" GOTOs, and oh my gosh what is that?! A GOTO!!!!! Keep
> methods "under 20 lines", and then I see a lot of huge methods.
> And it doesn't help when the tone I hear from the people and places
> saying "no" is one of near-finality, like these things should only be
> used in RARE circumstances.

The nice thing about this one is that is pretty easy to test: you can
write a moderate sized body of code both ways and decide for
yourself. Decided rationally and with code that otherwise follows
best practices, exceptions will win every time.

Adam

mike3

unread,
Jun 3, 2012, 12:04:51 AM6/3/12
to
But what if the error is not "exceptional", like an input parse error?
What happens if we were to use an exception because an error
has to propagate up several levels, but is not an "exceptional" error,
like a parse error?

Is it a good idea to default to exceptions for errors, and then if
after
you start actually using the code, it looks like an error code is more
appropriate, to use that instead?

> > Also, how exactly does one go about determining what is and is not
> > "exceptional"?
>
> You issue a command and expect it to succeed under normal working
> conditions. I.e. I expect that there's enough memory to complete the task,
> that there's enough space on FS to write, TCP connection delivers, the valid
> database operation carries out,  I can open the files the program created,
> or are there as part of the install.
>
> If any of those fail, it's exception.
>
> OTOH raw input form a user/outside world can be anything, so first it must
> be checked/sanitized. Failure is properly expected.
>

So does this mean the functions processing the input should return
error codes,
with all their messy glory?

<snip stuff I don't have any questions about>

> > This doesn't seem like a good idea. But what to do? Make every
> > function return an error code, using pointers to output variables to
> > store output, and only use exceptions for a rare few kinds of "system-
> > related" error? Yet one can hardly deny the niceness of being able to
> > say "x = f() + <foo>" (inside a "try" block, perhaps) instead of
>
> > if(f(&x) != SUCCESS)
> > { // handle error }
> > x += foo;
>
> > :)
>
> Exactly. The cheese  of error handling is the HANDLING part, not emitting
> the error via whatever means.  Concentrate on that, and the rest will be
> easy.
>

So does this mean to prefer an exception, since then we can do "x =
f() + <foo>"?

> In a normal system that use exceptions the catch stes are pretty rare, and
> most functions are exception-transparent.
>
> The function that detects a problem condition is normally clueless on what
> to do, and same goes for its immediate invoker... :)
>

Does this mean that we should prefer exceptions in that case, to allow
it to
propagate up to a higher level where something may be able to be done,
even
if the error is not "exceptional"? Whereas if we can handle it on-the-
spot, we
should use an error code? E.g.

> > Note how we can easily get LONG methods full of repeated code with
> > error codes (repeated error handlers to handle similar errors at
> > various function calls calling error-code-emitting functions, if one
> > wants to be more graceful than simply aborting with an error to the
> > next level up
>
> This sounds quite fishy. You either handle the error or not -- there is
> hardly place to be graceful.
>

I meant "if you have 10 calls to error-code-returning functions in
some
function, then _each and every one of those needs to be wrapped with
an error handler_". This significantly increases the length of the
original
function, and may obfuscate its purpose, by causing the code to be
dominated by checks/handlers. Not to mention if some of those handlers
function similarly, then we've got Duplicated Code(TM).

> > (which complicates what error codes a function can
> > return, since it can return its own codes in addition to those
> > returned by the functions below it, and those may have functions below
> > THEM, and so on...).). And who likes duplicated code? eww. This seems
> > a disadvantage of error codes.
>
> It is.
>

So then... "good idea to default to exceptions for errors, and then if
after
you start actually using the code, it looks like an error code is more
appropriate, use that instead"?

> > Or, and this is what I've been thinking of, use exceptions for every
> > error that the user does not have control over, like invalid input
> > strings. Would that be OK or excessive use of exceptions? And if we
> > are to mix error codes and exceptions, does this mean we should have
> > the lists of codes and exceptions correspond + a translator to
> > translate between the two?
>
> Why you think they shall be connected? Just use everything for its own
> benefit.

So it's OK to keep a distinct set of exceptions that's different from
the list of
return codes?

Luca Risolia

unread,
Jun 3, 2012, 12:13:47 AM6/3/12
to
"The C++ Programming Language" by Stroustrup. There is a whole chapter
dedicated to exceptions.

Adam Skutt

unread,
Jun 2, 2012, 11:45:55 PM6/2/12
to
On Jun 1, 9:44 pm, Pavel
<pauldontspamt...@removeyourself.dontspam.yahoo> wrote:
> Stefan Ram wrote:
> > Pavel<pauldontspamt...@removeyourself.dontspam.yahoo>  writes:
> >> I know you have already received lots of advice; but I think they omit an
> >> important factor, namely whether you are writing a library. In my experience, I
> >> found it quite annoying when the API of a library I use can throw.
>
> >    And that leads to an answer to the OP's question: When in Rome do as the
> >    Romans do!
>
> That's what I always profess. With exceptions, however, it might be unclear
> where's Rome and where's Athens. Just a quick example off the top of my head:
>
> When using STL, use std::exception hierarchy.
> When using WFC, use System::Exception.
> When using Qt, use return codes, but for passing errors between threads, inherit
> your exceptions from QtConcurrent::Exception
>

You're going to have to clarify what you mean by WFC. I don't think
it means what you think it means. If you mean the .NET runtime, then
you can't use that in C++, so it's somewhat irrelevant. C++/CLI is
not C++.

> When you write your own library that will most often used with WFC, often with
> Qt and always with some STL -- how shall you expose your errors?
>

With an exception, inheriting from an STL one if you must inherit from
one (since it is 'always' used), though your problem honestly makes
little sense.

> When you write your own library that uses WFC -- and of course STL how shall you
> expose your library's errors and where should you catch std::exception (which
> are fortunately rare) and guys from System::Exception hierarchy (which are much
> more often)?

In general, if you have to catch std::exception or System::Exception
outside of the entry point of your program[1][2], you've done
something pretty wrong. I think you're trying to create artificial
problems.

> When you write an application that uses all 3 or even only two libraries -- what
> errors shall you use inside your application? Many large application require
> particular processing of particular error conditions (error logs, alarms,
> interfaces to enterprise event handling systems, what's not) -- are you going to
> proliferate these exceptions? Usually, you don't.

Surely, write a catch block? You seem to be confusing the response to
a condition with the condition itself, but I don't see anything here
that requires "special" handling or creates a problem. Nevermind that
I'm not quite sure how you'd mix the 3 libraries you mentioned in the
first place.

> The benefits of uniform error
> processing aside, why will you want to make more parts of your code dependent on
> the libraries only because their exceptions may penetrate them and the errors
> are need to be processed there? What if you need to replace such a big library
> with another monster (e.g. to port your library). How are you going to tear
> these dependencies out?

Huh? The only way I can observe an exception from a given library is
if I'm actually calling functions within the library. As such,
needing to handle the exception can't possibly make me more dependent
on the library! You're going to need to provide an actual example of
what you're talking about.

If you're writing exception handlers to catch exceptions from
libraries you do not call (directly or indirectly), then you're doing
something completely and totally wrong.

> If you are a responsible designer, you will provide your own error processing
> layer and you will have to meticulously catch and either process or crack and
> refactor all errors before letting them further in a thin layer wrapping the
> library calls your application uses.

No, the code that responds to an error condition really shouldn't care
how you received the condition initially: if you're going to log a
message in response to an error, the logging code doesn't care if you
got an exception, bungled about with return codes, or just made things
up. The same goes for displaying dialogs and just about every other
conceivable response.

The entire point of exception handling is that if you cannot (or need
not) respond to the condition, /you pretend that it does not exist/
[3]. If you're doing something else, then you're designing your code
entirely incorrectly. Such behavior is the height of
irresponsibility, because it is a fool's errand. C++ libraries need
not declare every exception they throw, so without walking every line
of code of every library you use (directly or indirectly), one cannot
even accomplish what you say should be done.

> The code to capture error codes is simpler,
> shorter and faster than that needed to capture exceptions.

I don't see how it can ever be less code than exception handling[4].
At best, it can be equal, and in practice, it must necessarily be more
because you're explicitly doing things that are done implicitly with
exception handling.

>
> As a free bonus, you (or your user if you are the library writer) can always
> make a choice between writing throw and nothrow functions at no coding cost.

Hardly. Just returning error codes doesn't suddenly let you mark
everything nothrow, due to the problem I mentioned above.

>
> On top of this, following the code that only calls nothrow methods is much
> easier which increases the programmer's productivity.

I fail to see how calling a method marked nothrow increases my
productivity at all. It doesn't reduce what I need to be worried or
concerned about unless the code actually provides the nothrow safety
guarantee, which is considerably difficult.

Merely not throwing exceptions is of very little benefit to the
programmer.

> successful real-life applications and libraries (which is equivalent to saying
> "applications and libraries of significant size") have to spend more time on
> reading and understanding code of others than on writing their own code.

Funny, I spend more time trying to figure out what was written in all
these technical papers I'm supposed to implement than looking at
anyone's source code. YMMV I guess.

>
> Do your math yourself. I did mine many years ago and have never had a reason to
> be sorry of this my application of golden rule.

Unfortunately, the equation is changed, but based on what you've said
I think you did the calculation completely incorrectly in the first
place. Actually supporting your position with real code, which I
strongly encourage you to do, is going to be rather difficult.

Adam

[1] Or the entry point to a thread or similiar concurrency construct
[2] Though one should almost certainly 'catch(...)' in these contexts.
[3] Handling it here includes cleaning up resources and then kicking
the can down the road.
[4] The occasional syntax foible aside.

Ian Collins

unread,
Jun 3, 2012, 12:54:02 AM6/3/12
to
On 06/ 3/12 04:04 PM, mike3 wrote:
> On Jun 2, 5:08 pm, "Balog Pal"<p...@lib.hu> wrote:
>>
>> If you see abundance of try blocks, especially catch after a single call,
>> the function would be better off with return code.
>>
>> If you see return-code-football happening, like a row of
>> if ( (ret = Act())< 0)
>> return ret;
>> you'd be better off throwing, and a catch where actual handling happens.
>>
>> Certainly this applies to healthy, C++-style code, where objects take care
>> of themselves (see RAII), and no explicit management code is needed. If you
>> see free/delete/close... actions in the catch blocks and after those ifs,
>> fix that first.
>>
>
> But what if the error is not "exceptional", like an input parse error?
> What happens if we were to use an exception because an error
> has to propagate up several levels, but is not an "exceptional" error,
> like a parse error?

Well if the parser can't continue, it is exceptional. Both my XML and
JSON parsers make the reasonable assumption that the input documents are
well formed. If not, they throw an exception. In some cases the
exception is caught within the parser, augmented (say adding a line
number or the name of the malformed tag) and re-thrown. Given the
recursive nature of parsers, exceptions are an ideal choice.

>> You issue a command and expect it to succeed under normal working
>> conditions. I.e. I expect that there's enough memory to complete the task,
>> that there's enough space on FS to write, TCP connection delivers, the valid
>> database operation carries out, I can open the files the program created,
>> or are there as part of the install.
>>
>> If any of those fail, it's exception.
>>
>> OTOH raw input form a user/outside world can be anything, so first it must
>> be checked/sanitized. Failure is properly expected.
>>
>
> So does this mean the functions processing the input should return
> error codes, with all their messy glory?

There is no hard an fast rule.

If for example a function's job is to read an integer from a user, it
can keep prompting the user for the correct input until it gets it. If
it encounters an end of file condition it can't do its job so throw an
exception.

--
Ian Collins

BGB

unread,
Jun 3, 2012, 3:25:46 AM6/3/12
to
this can happen, but if one finds the best solution looking something
like a global or a goto, it may be better to look at whatever seems to
be leading to this "solution".


if one needs a goto because their function/method is a long winding
mess, then whether or not they should be using a goto is not really the
right question, but rather, the question may be better asked "what can I
do to break apart this function?".


and, sometimes, a global may be the right solution to a problem. at
other times, it may be a "solution" which comes back to bite later.

one may ask: why do I need this global?


>>> And also, perhaps I'm not necessarily so interested in rigid rules as
>>> to
>>> understand better how to make "good" code.
>>
>> Write alternatives and read them back. Ot show them for review.
>>
>
> You mean write the code and then read it to yourself? Write a method,
> sniff it with your own nose?
>
>> And no, you can't have a general solution for the concrete problems. No
>> silver bullets. You must think alternatives for every particular case.
>>
>
> I didn't think so. I was looking more for just what needs to be
> considered.
>

this is hard to explain, and harder to get right.

some people seem to be going at it more like "I have a hammer and
everything is a nail", but rarely does this work out ideally.


>>> A big problem is that I seem to find a lot of conflicting information.
>>
>> Just like the three blind guys go into "contradictions" describing the
>> elephant...
>>
>
> So does this mean the positions "use only exceptions" and "mix error
> codes with exceptions" and "use only error codes" are not as
> contradictory as they seem?
>

probably.

the people were feeling up different parts of the elephant, and coming
up with different answers.

programming is sort of the same way, where the optimal solution to a
problem will depend highly on what is being done.

most contradictions of this sort really aren't, but are rather the same
issue as seen from different perspectives.


one error is not the same as another, either in terms of its nature, or
in terms of its relative costs and the relative costs of the ways to
address it.

to some degree, programming is a big game of cost-benefit analysis.


>>> Some say use exceptions, others say use codes, others say use
>>> exceptions only when "exceptional", otherwise presumably use codes.
>>> But codes have a number of problems of their own (see the thread
>>> on comp.lang.c where I deal with C where there are no exceptions
>>> and only codes).
>>
>> Heh, is there a point in that discussion? It should be vwell known, that you
>> can have only two kinds of C code: the incorrect and the unreadable.
>> Exactly due to the lack of sensible centralized error handling, and
>> auto-cleanup. So any code that actually checks the return codes (that in C
>> have no realistic good alternatives) will be infested with all the checks
>> and cleanup actions. To a level you can't see what should go on.
>>
>
> Does this mean that C sucks?
>

some people feel this way.


I say a lot depends on what one is looking for.

C is hardly pleasant, easy to use, or results in pretty code.
there might be other reasons to use it though, so a lot depends.


>>> Which makes me want to use exceptions. And
>>> indeed, some say that -- use exceptions. But then I get this thing
>>> in my head saying "but maybe those people who say it should only
>>> be used in 'exceptional' circumstances have a good point".
>>
>> Did you try the 'five whys' method?
>>
>> Sure they have some point. Dig out what it is, and you can decide whether it
>> applies to your case or not.
>>
>
> So then you should ask "why? why? why?" to ALL these rules -- use
> only exceptions, use exceptions only when "exceptional" with error
> codes
> for everything else, use only error codes, never make a method more
> than
> X long (20 lines, one screen, etc.), never use a global, never use a
> goto,
> avoid singleton, etc.?
>


I once worried a lot about rules (although, in my case, it was worrying
more about the nature of ethics and morality).

ultimately, I noted a few things:
it all basically boils down to cost-benefit analysis;
not all cost-benefit is necessarily self-serving;
the line between helping oneself and helping others is nowhere near as
clearly defined as people make it out to be (there is heavy emphasis
placed on "helping oneself at the expense of others" vs "helping others
and asking nothing for oneself", but ultimately this may be itself, for
the most part, a false dichotomy, and "oneself vs others" is not really
asking the right question).


sadly, I don't know of any good way to explain this one.
this doesn't sound like a good strategy.


better would be not to try to memorize anything, but to try to
understand why these rules exist.

knowing words will ultimately not buy one a whole lot, if one doesn't
really understand what the words mean.


often, it is not about memorizing or knowing specific things, but
rather, about understanding why things are as they are in the first
place (how they came to be, and where they are going in the future).


yeah, this doesn't answer a whole lot, but I have little idea how to
explain what I am thinking here.

Paavo Helde

unread,
Jun 3, 2012, 4:49:35 AM6/3/12
to
mike3 <mike...@yahoo.com> wrote in
news:7fa26d34-4ce8-468e...@f8g2000pbf.googlegroups.com:

>>
>> > Does this mean that if
>> > we have a program, and we have a "parse()" function that parses a
>> > string input by the user, that this function should return an error
>> > code on parse failure, instead of throwing an exception? Yet we'll
>> > probably also come across places where it's good to use an
>> > exception, in the same program! Which means we get into _mixing
>> > error codes and exceptions_. And what's the best way to do that?
>
> But what if the error is not "exceptional", like an input parse error?

It depends; for example, if there is only one way to interpret the input,
and the input is invalid according to this way, this is an error which
should not have happened, and an exception is the right choice.

On the other hand, if there are several ways to interpret the user input,
and the program tries one after another and selects the first way that
works, then there is no error when one of tries fails, and it should not
be reported by an exception. However, when all attempts to interpret the
input fail, then this becomes an error and should be reported by an
exception.

The problem with this schema is that the functions become hard to reuse
as in some cases they should report errors by throwing and in other cases
by returning an error code or equivalent. How one solves this is a matter
of taste and also some technical issues (if the code is speed-critical
then one cannot use the solution of throwing and catching as this can
become quite slow).

Maybe the cleanest solution in C++ would be to use template
functions/classes, with a policy template parameter which specifies the
behavior in case of an error. This solution would be also most of the
work.

In some simpler cases a "default value" parameter to a function might
also work well: if the parameter is passed in by the caller, the function
would return it in case of an error; if the parameter is omitted at the
call site, the function would throw in case of an error.


> What happens if we were to use an exception because an error
> has to propagate up several levels, but is not an "exceptional" error,
> like a parse error?
>
> Is it a good idea to default to exceptions for errors, and then if
> after
> you start actually using the code, it looks like an error code is more
> appropriate, to use that instead?

Very low-level functions are sometimes better off with returning an error
code as at this low level it is sometimes not known which approach is
more appropriate. Many C standard library functions like strtod() fall in
this class - these should not throw exceptions even if they could.

However, the immediate caller of such a low-level function like strtod()
should immediately decide whether to throw an exception or return zero,
for example; passing the same error code upstream is a no-no.

>> > Also, how exactly does one go about determining what is and is not
>> > "exceptional"?

Anything which should not happen in a normal workflow is exceptional.
There is some wiggle room as always, of course. If a mkdir() call fails
because the directory already exists, is this exceptional or not?

>> You issue a command and expect it to succeed under normal working
>> conditions. I.e. I expect that there's enough memory to complete the
>> task
> ,
>> that there's enough space on FS to write, TCP connection delivers,
>> the va
> lid
>> database operation carries out,  I can open the files the program
>> creat
> ed,
>> or are there as part of the install.
>>
>> If any of those fail, it's exception.

Yes.

>> OTOH raw input form a user/outside world can be anything, so first it
>> mus
> t
>> be checked/sanitized. Failure is properly expected.

I am happily throwing exceptions also if the user input is invalid. This
should not happen in a "normal" workflow. Note that the parse() function
should not know or care if the input comes from an interactive user or
from a disk file.

YMMV, of course.

>
> So then... "good idea to default to exceptions for errors, and then if
> after
> you start actually using the code, it looks like an error code is more
> appropriate, use that instead"?
>
>> > Or, and this is what I've been thinking of, use exceptions for
>> > every error that the user does not have control over, like invalid
>> > input strings. Would that be OK or excessive use of exceptions? And
>> > if we are to mix error codes and exceptions, does this mean we
>> > should have the lists of codes and exceptions correspond + a
>> > translator to translate between the two?
>>
>> Why you think they shall be connected? Just use everything for its
>> own benefit.
>
> So it's OK to keep a distinct set of exceptions that's different from
> the list of
> return codes?

Sure; the exception objects cannot be handled by the same code as error
codes anyway, so there is no need to make them "compatible" in any way.
Also, it would become very tedious to add a new exception class for each
possible error code value. A new exception class should be added only if
there is a strong indication that it must be handled in some specific way
by the client code.

Cheers
Paavo

Balog Pal

unread,
Jun 3, 2012, 7:04:19 AM6/3/12
to

"mike3" <mike...@yahoo.com>
>> > So where could I get examples of _well-written_, _well-designed_,
>> > _smell-free_ error handling in a _non-trivial_ program?
>>
>> Why would you need examples?
>>
>> K-PEX-ians would likely say that any inelligent being is well capable of
>> telling right from wrong -- you even demonstrated it in the initial
>> message,
>> so all you lack is self-confidence. ;-)
>>

>What are "K-PEX-ians"?

A typo :( I meant K-PAX-ians. http://www.imdb.com/title/tt0272152/quotes
I just looked at the page, it has the quote right at the first spot. :)

>> You see the noise and repetition caused by mis-application of a method.
>> So
>> just think the alternatives and chose the one that has least of those
>> problems.

>What if one of the alternatives that looks good is something often
>considered
>"bad"? Like a global, or a goto?

Considered by who? As we are at it, do you actually believe the goto-bashing
morons?
In C, hosed of other tools, goto has mainstream use for the very topic we
discuss. Functions have double or one-and-a-half exit. The if( ) invocations
checking the status do a goto error_exit or goto cleanup.

Creating the best of what can be done for correctness, preserving the
maximum of readability. Certainly still far from the ideal.

And it is quite easy to put the alternatives side by side and watch
defenders of the "no goto" way to sweat explaining how the extra flags,
extra assignments, extra lines, duplicate code -- or the MACROs to mitigate
it should be considered better. You don't even need to ask the question
"now explain me, who is here really get confused by seeing that goto
cleanup or cleanup: -- and why we keep paying him?

Anyone can shout good or bad -- it has little/no info, skip directly to the
explanation part. If it's missing or speculative, well, guess what. ;-)

>> > And also, perhaps I'm not necessarily so interested in rigid rules as
>> > to
>> > understand better how to make "good" code.
>>
>> Write alternatives and read them back. Or show them for review.
>>

>You mean write the code and then read it to yourself? Write a method,
>sniff it with your own nose?

Yes.


>> And no, you can't have a general solution for the concrete problems. No
>> silver bullets. You must think alternatives for every particular case.

>I didn't think so. I was looking more for just what needs to be
>considered.

Elswhere it was mentioned that writing exception-safe code is hard, maybe as
hard as correct MT. The last part is certainly not true, but there are some
gotchas, and you must be aware of them. Indeed it is easy to make some naive
mistakes that craete nasty bugs.

So before you jump on exceptions read at least the first too books of Herb
Sutter.

On the bright side we can state that a code that is not exception-safe and
needs adjusting is very-very likely wrong anyway, and needs the same
transformation for different reasons even without exceptions.

Basicly you need to look for code that has side effects avoid having too
many (mean more than 1 :) side effects in an expression.


>> > A big problem is that I seem to find a lot of conflicting information.
>>
>> Just like the three blind guys go into "contradictions" describing the
>> elephant...
>>

>So does this mean the positions "use only exceptions" and "mix error
>codes with exceptions" and "use only error codes" are not as
>contradictory as they seem?

Sure. The main guide is "do the right thing -- and for the right reasons".
May seem vague but works out in practice, and if you have a culture of code
reviews and team retrospectives (based on true openness) you even avoid
getting blinded by your own light. ;-)

>> > Some say use exceptions, others say use codes, others say use
>> > exceptions only when "exceptional", otherwise presumably use codes.
>> > But codes have a number of problems of their own (see the thread
>> > on comp.lang.c where I deal with C where there are no exceptions
>> > and only codes).
>
>> Heh, is there a point in that discussion? It should be vwell known, that
>> you
>> can have only two kinds of C code: the incorrect and the unreadable.
>> Exactly due to the lack of sensible centralized error handling, and
>> auto-cleanup. So any code that actually checks the return codes (that in
>> C
>> have no realistic good alternatives) will be infested with all the checks
>> and cleanup actions. To a level you can't see what should go on.
>

>Does this mean that C sucks?

Of course it does. What doesn't. Quoting Stroustrup: "The major cause of
complaints is C++ undoubted success. As someone remarked: There are only two
kinds of programming languages: those people always bitch about and those
nobody uses." It applies to C and many others.

C sucks for having very few tools, so you must spread complexity in the code
itself. Other languages suck because they have many tools, so the user must
learn them, use them correctly, and deal with the fact that the same thing
can be done n so many different ways.


>> Did you try the 'five whys' method?

>So then you should ask "why? why? why?" to ALL these rules -- use
>only exceptions, use exceptions only when "exceptional" with error
>codes for everything else, use only error codes, never make a method more
>than X long (20 lines, one screen, etc.), never use a global, never use a
>goto, avoid singleton, etc.?

No, you ask one why on the rule, and keep asking why on the answers you get
recursively. Until you reach the roots. (Or discover there is no foundation
really just thin air.)

>> Huh. Did you ever hear people saying that any guideline is only as good
>> as
>> you understand its rationale?
>>
>> I met a plenty of those "NO" guys, asked the 5 whys, most started to
>> sweat
>> blood right at the first, or didn;t even understand what "why" means and
>> if
>> he supposed to provide some answer.

>Isn't that a BIG problem if "most" fail to understand these reasons?

Sure it is. But that't the fact of life. Software creation (I'd not call it
engineering) is still in the wild west era. There are no quality controls on
any level -- especially on the consumer side that would drag the rest. Big
majority of the projects just fail to deliver or by delivery uses up 3 or
more times the budget and/or time. And the result is not pleasing.

I recall a fine red book from almost 30 years ago -- Ashton Tate's intro to
dBase III, where uncle Fred created the program to cover his fish-selling
shop. Using this shiny new tool, and reading this simple manual. And it was
a good book, I certainly could use it to write the programs just as
expected. But uncle Fread will not and can not. Ever since, no matter how
many shinier tools were created and how computers enetered the everyday
life.

Writing correct programs is just hard, and few can do it. The majority of
people involved in the industry can onjly provide stuff the "looks like
working" at best, or dragging down the overall project as baseline.

But shhhh, the Political Correctness cops say we are not supposed to reveal
that, and pretend that everyone is equally good ignoring all the
counter-evidence.

So I keep suggesting to ignore the loudness, and check only the rationales
given.


>Does this mean I should get to work spending a lot of time memorizing
>rationale?

Memorizing? No, a good rationale will just conquer your mind, and will pop
up as soon as you see something contradicting.

you need to read, study, understand the rationales, accept or reject them
for yourself. The rest just happens.

>Where can I find detailed rationale for all these rules --
>no long method,
>no global, no goto, exceptions vs error codes, etc. so as to be able
>to know
>enough rationale to pass the "5 whys test"?

The Sutter/Alexandrescu book I already mentioned is a fine start.

Rui Maciel

unread,
Jun 3, 2012, 7:55:53 AM6/3/12
to
mike3 wrote:

> But what if the error is not "exceptional", like an input parse error?
> What happens if we were to use an exception because an error
> has to propagate up several levels, but is not an "exceptional" error,
> like a parse error?
>
> Is it a good idea to default to exceptions for errors, and then if
> after
> you start actually using the code, it looks like an error code is more
> appropriate, to use that instead?

It really depends on what you define as an input parser error. Lexers are
designed to identify certain string patterns as specific tokens, while
identifying everything else as a very specific token; the "unknown token"
token. So, stumbling on an unknown token isn't necessarily an exceptional
event. The same applies to grammar errors. A set of tokens is either
matched by your grammar or it isn't. In some cases, a grammar might be
defined so that a specific sequence of tokens is recognized but interpreted
as an error. Either way, your parser still ends up in a recognized state,
and therefore these errors aren't exceptional situations.


> So does this mean the functions processing the input should return
> error codes, with all their messy glory?

That's up to whoever is in charge of designing the software. More
specifically, it must be decided which situation is expected and required to
express the control flow of your program and which situation is exceptional,
and therefore, for reasons such as clarity, it is benefitial to handle it
separately from the main control flow.

As an example, it's a good idea to write a lexer so that, when stumbling on
gibberish, it returns an error code signaling just that. By doing so, it is
possible to set the parser to handle the not so exceptional event of parsing
an ill-formed document, which might include the ability to throw a context-
dependent error message or even resume parsing. This wouldn't be easy or
simple to pull off if your lexer threw an exception when stumbling on
gibberish.


Rui Maciel

Balog Pal

unread,
Jun 3, 2012, 9:05:09 AM6/3/12
to
"mike3" <mike...@yahoo.com>
>Is it a good idea to default to exceptions for errors, and then if after
>you start actually using the code, it looks like an error code is more
>appropriate, to use that instead?

Yes. As I mentioned for some operations there's a need for both forms.
Fortuneately it's not hard to write converters in either direction, and then
clients can use the better-suited variant.

>> OTOH raw input form a user/outside world can be anything, so first it
>> must
>> be checked/sanitized. Failure is properly expected.

>So does this mean the functions processing the input should return
>error codes, with all their messy glory?

Don't confuse the situations and it's not that messy really.

In that layer you will have functions that return status. IsEmailValid()
shall not throw, but return bool, or some more detailed info on the
diagnosed problem. When you check the input you will call a ton of such
functions, and the caller will know how to act on discrepancy.

While those functions return "error code", it is not really that from the
function's perspective: it does all its work properly and that is the
result. It only becomes error code if the caller decides to not act, but
pass it upwards.

> So does this mean to prefer an exception, since then we can do "x = f() +
> <foo>"?

Yes, that is the main motivation. To separate the action logic and the
error-reaction logic. Not mix and tangle them together.

>Does this mean that we should prefer exceptions in that case, to allow it
>to
>propagate up to a higher level where something may be able to be done, even
>if the error is not "exceptional"? Whereas if we can handle it on-the-spot,
>we
>should use an error code? E.g.

By using the previously mentioned form you already admitted that the error
condition *is* exceptional.

If that invocation form is correct, it implies that
- involved operations are expected to succeed
- this spot has no interest in looking at error conditions

If the code expected some problem and had alternative actions in mind for
that condition, it would be there, wouldn't it?

>So then... "good idea to default to exceptions for errors, and then if
>after
>you start actually using the code, it looks like an error code is more
>appropriate, use that instead"?

Yes. Certainly don't forget to provide at least the basic exception
guarantee, and learn about tha Abrahams principles if you didn't yet.

>So it's OK to keep a distinct set of exceptions that's different from
>the list of return codes?

Those facilities serve some purpose. If you meet that purpose you're okay.
Does not matter how you do that.

In usual good code 95% of catch() blocks just do a conversion to some
different exception or a return code.

The rest minority that actually does something -- and it will just catch
*any* exception (with luck the common base class for all), and just call
.what() for a single string.

And that is more than enough. Top levels only care if stuff worked or not.
Rollback actions are issued via destructors (or simply lack of commit). The
inforlation on the problem trigger is carried in the exception object and
can present itself to a human-readable form so some actual intelligence,
outside the program can figure out what next.


Adam Skutt

unread,
Jun 3, 2012, 8:40:32 AM6/3/12
to
On Jun 2, 7:08 pm, "Balog Pal" <p...@lib.hu> wrote:
> > I've heard about this, and wonder when is it right to use codes, and
> > when to use exceptions for reporting errors?
>
> Simple guide is that you use return code if the immediate caller is supposed
> to care about the failure details and act. While throw is for long-range
> communication.  Not surprizingly for some functions both make sense.

I would love an example of this, because I've never seen such a
determination made, much less correctly.


> > Also, how exactly does one go about determining what is and is not
> > "exceptional"?
>
> You issue a command and expect it to succeed under normal working
> conditions. I.e. I expect that there's enough memory to complete the task,
> that there's enough space on FS to write, TCP connection delivers, the valid
> database operation carries out,  I can open the files the program created,
> or are there as part of the install.
>
> If any of those fail, it's exception.
>
> OTOH raw input form a user/outside world can be anything, so first it must
> be checked/sanitized. Failure is properly expected.

Expectation isn't enough to decide to not throw an exception. You
require both the expectation that the condition will happen and the
ability to respond to it. For a error code, you must be certain that
the proper place to respond is in the immediate caller.

The ability to make such a determination is extremely rare, including
for invalid input. Exceptions should be the normal response to
invalid input to a function, including to invalid input supplied by
the outside world.

>
> Depends on what is asking. If your program code that should have obey the
> bounds, then it is a completely different field, that of assert() and
> terminate() due to detected bug.

Perhaps, if you can determine it was programmer error. I'm not sure
the different behavior is really justified in the few cases where that
is possible.

> > Throw exception? See, what I've currently been doing, and
> > it's probably silly, is to use exceptions when our function needs to
> > return a value, and error codes when it could otherwise return "void".
>
> Certainly the function is hosed. :) exception looks like the easy way out.
> But that holds only locally. If the caller thought the bounds were okay, and
> turned out wrong, who shall handle the exception and how?

Perhaps no one, and that's perfectly fine. Just because an exception
is thrown doesn't mean it needs to be caught ever.

>
> OTOH you can define the function as 'best-effort', and allow blind calls.
> Definig the behavior as you like, including to throw or return some default
> ot NULL object.  (consider a sparse matrix with unlimited size, that holds
> only values for cells explicitly set, and for anything else returns 0.)

I don't know the value of an unlimited size matrix, nor how this would
work here.

Adam

Nobody

unread,
Jun 3, 2012, 9:50:28 AM6/3/12
to
On Sun, 03 Jun 2012 01:08:53 +0200, Balog Pal wrote:

> If you see abundance of try blocks, especially catch after a single call,
> the function would be better off with return code.

Assuming that the abundance of try blocks isn't just a case of the
programmer not understanding exceptions.

Balog Pal

unread,
Jun 3, 2012, 10:33:08 AM6/3/12
to
"Adam Skutt" <ask...@gmail.com>

>> Simple guide is that you use return code if the immediate caller is
>> supposed
>> to care about the failure details and act. While throw is for long-range
>> communication. Not surprizingly for some functions both make sense.

>I would love an example of this, because I've never seen such a
>determination made, much less correctly.

MFC's CFile class has:

-ctor that takes filename, opens file and throws CFileException on a
problem.
-ctor that takes nothing and does not open the file
.Open() that takes filename, opens and return TRUE on success.

So where I expect the file to be there, I use the first form.

In other case the second. It's not at all uncommon to look for a file at
multiple different locations, all being optional. Or attempt to write a file
at some sensible location and fall back to ask the user if it can't be
created there.

>The ability to make such a determination is extremely rare, including
>for invalid input. Exceptions should be the normal response to
>invalid input to a function, including to invalid input supplied by
>the outside world.

That opens slippery slope for mixing program logic errors with environmental
factors outside our control.

>> Depends on what is asking. If your program code that should have obey the
>> bounds, then it is a completely different field, that of assert() and
>> terminate() due to detected bug.

>Perhaps, if you can determine it was programmer error. I'm not sure
>the different behavior is really justified in the few cases where that
>is possible.

Come on! If a function has a precondition, then the programmer, the caller
is responsible to meet it.
If it is not met, it *is* a programmer error. Not cosmic rays or wrath of
God or anything.

And IMO systems based on contracts was beating those without anywhere in the
real world.

>> > Throw exception? See, what I've currently been doing, and
>> > it's probably silly, is to use exceptions when our function needs to
>> > return a value, and error codes when it could otherwise return "void".
>
>> Certainly the function is hosed. :) exception looks like the easy way
>> out.
>> But that holds only locally. If the caller thought the bounds were okay,
>> and
>> turned out wrong, who shall handle the exception and how?

>Perhaps no one, and that's perfectly fine. Just because an exception
>is thrown doesn't mean it needs to be caught ever.

It is not fine. If the program derailed, it is in a state its creators
thought be impossible, any further action has fair chance to make thing even
worse. Unwinding the stack to some default habdler before exit IS further
action. Even if there is no handler, C++ does not specify whether stack
unwinding happens or not before terminate() gets called.

So throwing instead of halting is a fishy practice.

Also, in a program written in C++ that has any basic quality controls the
most likely cause hitting an assert failure is undefined behavior. And once
the behavior is undefined, do you think further will be good?


nick_keigh...@hotmail.com

unread,
Jun 3, 2012, 10:28:33 AM6/3/12
to
and he discusses the reasons for the invention of exceptions.

I saw it most clearly when I reimplemented a simple socket program in Python where before it had been in C. The Python using exceptions was much clearer. The application was clearly separated from the error handling.

Rui Maciel

unread,
Jun 3, 2012, 11:38:42 AM6/3/12
to
mike3 wrote:

> A big problem is that I seem to find a lot of conflicting information.
> Some say use exceptions, others say use codes, others say use
> exceptions only when "exceptional", otherwise presumably use codes.
> But codes have a number of problems of their own (see the thread
> on comp.lang.c where I deal with C where there are no exceptions
> and only codes). Which makes me want to use exceptions. And
> indeed, some say that -- use exceptions. But then I get this thing
> in my head saying "but maybe those people who say it should only
> be used in 'exceptional' circumstances have a good point". And
> then I'm once again confused. And then what "exceptional" means
> is itself, apparently dependent on the speaker.

In some cases, both exceptions and error codes are adequate solutions.
Therefore, it isn't necessarily wrong or a bad idea to use either one in
those cases, and the decision to pick one tends to be a design decision.
Hence the apparently conflicting suggestions.

Personally, I see exceptions as a way to handle errors in a sequence point
other than the one immediately after where the errors are thrown. As a
downside, when you throw an exception you explicitly declare that you don't
know or even care which sequence point will be executed next. You trust
that the exception catching code does the right thing, and that the
program's execution will resume in a safe, innocuous sequence point.


> Would I be right to think the best thing to do here is just pick an
> approach and see where it goes, don't bother worrying who's more
> "right"? Is this just one of those things that simply does not have
> a pat, objective answer, and so you have to do some picking and
> choosing and seeing what happens?

That sounds like a recipe for a mild disaster. After all, if you use a tool
without even thinking if it is the right one for your job then how do you
even know it is a good idea to use it?

A decent rule of thumb that helps see which solution is better suited is as
follows:
- if you are dealing with exceptional circumstances which can be omitted
from the control flow of your code without jeopardizing clarity or
readability (i.e., memory allocation errors, sanity checks failing in an
unexpected way, network connections breaking up, etc...) then exceptions may
be a good way to go.
- if, instead, you are dealing with expectable errors which directly
influence the control flow of your code to the point you can't express an
algorithm without explicitly covering them then returning error codes may be
a good way to go.

Other than this, it's a matter of understanding how exceptions and error
codes work, particularly their downsides, and make a design decision on
which one to pick to handle a particular error.


Rui Maciel

Adam Skutt

unread,
Jun 3, 2012, 11:52:02 AM6/3/12
to
On Jun 3, 10:33 am, "Balog Pal" <p...@lib.hu> wrote:
> "Adam Skutt" <ask...@gmail.com>
>
> >> Simple guide is that you use return code if the immediate caller is
> >> supposed
> >> to care about the failure details and act. While throw is for long-range
> >> communication. Not surprizingly for some functions both make sense.
> >I would love an example of this, because I've never seen such a
> >determination made, much less correctly.
>
> MFC's CFile class has:
>
> -ctor that takes filename, opens file and throws CFileException on a
> problem.
> -ctor that takes nothing and does not open the file
> .Open() that takes filename, opens and return TRUE on success.
>
> So where I expect the file to be there, I use the first form.
>
> In other case the second. It's not at all uncommon to look for a file at
> multiple different locations, all being optional. Or attempt to write a file
> at some sensible location and fall back to ask the user if it can't be
> created there.

Yes, but that's hardly justification for the additional complications,
especially since there is no guarantee that "missing optional file"
will be handled in the caller, or that asking the user can be
performed in the caller. It's a dubious argument at best.

>
> >The ability to make such a determination is extremely rare, including
> >for invalid input.  Exceptions should be the normal response to
> >invalid input to a function, including to invalid input supplied by
> >the outside world.
>
> That opens slippery slope for mixing program logic errors with environmental
> factors outside our control.

That slippery slope was opened before the application was even ever
started. How does a file open call distinguish between a string
supplied by the user and a constant within the program? It can't, so
it's a waste of time to try. The same applies to database connection
strings, usernames and passwords, and a whole host of other inputs
that are sometimes hardcoded into applications.

>> Depends on what is asking. If your program code that should have obey the
>> bounds, then it is a completely different field, that of assert() and
>> terminate() due to detected bug.
> Perhaps, if you can determine it was programmer error. I'm not sure
> the different behavior is really justified in the few cases where that
> is possible.
> Come on!  If a function has a precondition, then the programmer, the caller
> is responsible to meet it.
> If it is not met, it *is* a programmer error.  Not cosmic rays or wrath of
> God or anything.

Sure, but the sort of things that were being discussed aren't ipso
facto preconditions of that sort. Asking for a non-existent tile on
the map might be a programming bug (e.g., an invalid position
calculation) or it might be invalid input (e.g., invalid input from a
client in a multiplayer game).

Again, even when you do know it must be a programming error, abrupt
termination is hardly a good policy. It's possible the bug can be
worked around by the user, even to simply save their work and quit.
Merely raising the exception achieves the desired response and leaves
space for better handling of programming bugs, compared to immediate
termination.

> >> Certainly the function is hosed. :) exception looks like the easy way
> >> out.
> >> But that holds only locally. If the caller thought the bounds were okay,
> >> and
> >> turned out wrong, who shall handle the exception and how?
> >Perhaps no one, and that's perfectly fine.  Just because an exception
> >is thrown doesn't mean it needs to be caught ever.

>
> It is not fine. If the program derailed, it is in a state its creators
> thought be impossible, any further action has fair chance to make thing even
> worse.

Not all bugs yield undefined behavior, so this statement is just
false. If your code is exception transparent, then it doesn't matter
whether a function threw due to a programming error or invalid input
from the user or because the operation actually failed.

And if you can't write exception transparent code, then this whole
discussion is moot.

> Unwinding the stack to some default habdler before exit IS further
> action. Even if there is no handler, C++ does not specify whether stack
> unwinding happens or not before terminate() gets called.

So?

> Also, in a program written in C++ that has any basic quality controls the
> most likely cause hitting an assert failure is undefined behavior. And once
> the behavior is undefined, do you think further will be good?

I'm not sure I believe that would be the most likely cause. But even
it if were, trying to do something sensible and failing has the same
result as terminating on the spot. If you make things worse trying to
cleanup, then your cleanup code was broken to begin with. It was
going to make things worse even under defined failure conditions.

Adam

DSF

unread,
Jun 3, 2012, 3:32:17 PM6/3/12
to
On Wed, 30 May 2012 11:31:24 -0700 (PDT), Adam Skutt
<ask...@gmail.com> wrote:

>The Windows model is no such thing. Even if it were, it doesn't
>change the fact that many applications are run in contexts where they
>have no ability to correct invalid input: they simply must reject it.
>Termination is a perfectly cromulent way to reject invalid input for
>many applications in these situations.
>

(With tongue firmly in cheek.)

I strongly disagree with you on exception handling. I want to
dislike you, but you go and make a Simpsons reference.

That embiggens you in my opinion!

DSF

DSF

unread,
Jun 3, 2012, 3:47:29 PM6/3/12
to

{snip}
> Pavel<pauldont...@removeyourself.dontspam.yahoo> writes:
> If you are a responsible designer, you will provide your own error processing
> layer and you will have to meticulously catch and either process or crack and
> refactor all errors before letting them further in a thin layer wrapping the
> library calls your application uses.

On Sat, 2 Jun 2012 20:45:55 -0700 (PDT), Adam Skutt <ask...@gmail.com>
wrote:
>No, the code that responds to an error condition really shouldn't care
>how you received the condition initially: if you're going to log a
>message in response to an error, the logging code doesn't care if you
>got an exception, bungled about with return codes, or just made things
>up. The same goes for displaying dialogs and just about every other
>conceivable response.
>
>The entire point of exception handling is that if you cannot (or need
>not) respond to the condition, /you pretend that it does not exist/
>[3]. If you're doing something else, then you're designing your code
>entirely incorrectly. Such behavior is the height of
>irresponsibility, because it is a fool's errand. C++ libraries need
>not declare every exception they throw,

...but they should, or at least declare that they throw or don't
throw.

> so without walking every line
>of code of every library you use (directly or indirectly), one cannot
>even accomplish what you say should be done.

This is the problem I have with exception handling: you CANNOT
ignore exceptions. You must in some manner handle the possibility,
else your program ENDS! Handling minor, recoverable, errors with
throwing exceptions is like police shooting jaywalkers.

Often, how you recover from an error depends on the specific error
information. If you "try" each individual function that might throw,
you might as well have error codes. The larger the "try" block, the
more difficult to isolate and repair/recover from the damage becomes.

So if I wind up using a library written by someone who throws an
exception for every incorrect condition, large or small, I have to
handle all of them or "throw the baby out with the bath water."

I do think they are a great way to handle an error where there is no
elegant return path, such as a boolean return value. (Is it "yes,"
"no," or "out of memory"?

Error conditions more often represent "that didn't work, I'll try
this" than "it's the end of the world!"

DSF

Rui Maciel

unread,
Jun 3, 2012, 4:45:02 PM6/3/12
to
Adam Skutt wrote:

> The entire point of exception handling is that if you cannot (or need
> not) respond to the condition, you pretend that it does not exist.

A while ago I was working on an application that used Qt for the GUI and
Eigen for linear algebra. Long story short, under some circumstances Eigen
threw an exception and Qt caught it. And when Qt caught it, it terminated
the process.

So, if you follow your own advice then you better be prepared to deal with
its consequences.


Rui Maciel

Adam Skutt

unread,
Jun 3, 2012, 4:56:41 PM6/3/12
to
On Jun 3, 3:47 pm, DSF <notava...@address.here> wrote:
> {snip}
>
> > Pavel<pauldontspamt...@removeyourself.dontspam.yahoo>  writes:
> > If you are a responsible designer, you will provide your own error processing
> > layer and you will have to meticulously catch and either process or crack and
> > refactor all errors before letting them further in a thin layer wrapping the
> > library calls your application uses.
>
> On Sat, 2 Jun 2012 20:45:55 -0700 (PDT), Adam Skutt <ask...@gmail.com>
> wrote:
>
> >No, the code that responds to an error condition really shouldn't care
> >how you received the condition initially: if you're going to log a
> >message in response to an error, the logging code doesn't care if you
> >got an exception, bungled about with return codes, or just made things
> >up.  The same goes for displaying dialogs and just about every other
> >conceivable response.
>
> >The entire point of exception handling is that if you cannot (or need
> >not) respond to the condition, /you pretend that it does not exist/
> >[3].  If you're doing something else, then you're designing your code
> >entirely incorrectly.  Such behavior is the height of
> >irresponsibility, because it is a fool's errand.  C++ libraries need
> >not declare every exception they throw,
>
>   ...but they should, or at least declare that they throw or don't
> throw.

They should declare what they know, but that might not be everything
that is possible to be thrown. Templates means that you have to work
with unknown types with unknown exception specifications. Yet, it's
perfectly possible to write code that works with the STL and other
libraries without this being a problem. So there's no reason to
believe that code should fully declare what exception types can be
thrown (generally)--the notion that this is unnecessary is baked into
the C++ standard library. Me, personally, I try to work with the
standard library, not against it.

>   This is the problem I have with exception handling: you CANNOT
> ignore exceptions. You must in some manner handle the possibility,
> else your program ENDS!

Which is not a problem. I don't know why people think program
termination, especially in response to an error, is such a crime.
There's nothing inherently bad nor evil about it.

> Handling minor, recoverable, errors with
> throwing exceptions is like police shooting jaywalkers.

It is nothing of the sort. As I've asked many others, how exactly do
you determine whether an exception will be minor and/or recoverable
for any given application when you're writing a function, especially a
function in a general library? You can't. Even when you do know,
baking policy into such a function leads to brittle, unreusable, low
quality code. Just because it's a minor problem today does not mean
it will be a minor problem tomorrow.

Look at the C, POSIX, and Win32 APIs if you don't believe me: the
error codes returned by these functions describe the event that
occurred and nothing else. They generally make zero effort to
indicate whether a specific operation can be retried, or should be
retried[1], once the condition is raised. That distinction is left
entirely up to the caller to determine.

>
>   Often, how you recover from an error depends on the specific error
> information. If you "try" each individual function that might throw,
> you might as well have error codes. The larger the "try" block, the
> more difficult to isolate and repair/recover from the damage becomes.

If you're wrapping each individual function in a try block, you're
doing something very wrong. You're going to have to support the second
statement with actual code examples, as I don't understand what yo're
taking about. Correct exception handling means you don't care about
where an exception originated, but only about where you can handle
it. There's no need to "isolate" anything.

>
>   So if I wind up using a library written by someone who throws an
> exception for every incorrect condition, large or small, I have to
> handle all of them or "throw the baby out with the bath water."
>

No, you only need to handle the ones you can trigger and respond to.
That rarely means all of them.

>   Error conditions more often represent "that didn't work, I'll try
> this" than "it's the end of the world!"

Utter nonsense. The return codes from std::fopen, as one of example
of many, may be fatal or not-fatal depending on the what the
application is doing. Some of them may also represent programming
errors, depending on what the application is doing. Just like you
can't say, "This exception represents a minor event", you can't
generally say the same thing about error codes!

Adam

[1] POSIX EINTR and EAGAIN being the most noticable exceptions.
However, not every situation where EAGAIN can be raised should be
automatically retried, so even it is not that simple.

Adam Skutt

unread,
Jun 3, 2012, 4:59:25 PM6/3/12
to
Qt clearly says on its wrapper that it is not exception safe and has
said so since its inception AFAIK. Broken software doesn't really
impact my position any, though I suppose I should have mentioned
upfront that there's a depressing amount of software out there that
lacks exception safety.

Adam

Balog Pal

unread,
Jun 3, 2012, 5:20:24 PM6/3/12
to
"DSF" <nota...@address.here>
> This is the problem I have with exception handling: you CANNOT
> ignore exceptions. You must in some manner handle the possibility,
> else your program ENDS!

Not too realistic, as normally you have some general catch blocks at high
points.

> Handling minor, recoverable, errors with
> throwing exceptions is like police shooting jaywalkers.

You want to say: minor conditions that the program COULD have handled if the
programmer actually bothered with that -- but did not. So the deployed state
CAN NOT tell it from any other overlooks, and evaluate the severity.

Like in the joke: Computer, cut the patient's left leg. I said the left! I
said the LEG!

You want to cure the sloppy programs by letting them go derailed. And
believe it is for the good. Hmm.

> Often, how you recover from an error depends on the specific error
> information. If you "try" each individual function that might throw,
> you might as well have error codes. The larger the "try" block, the
> more difficult to isolate and repair/recover from the damage becomes.

Hardly. In the catch you most often just not the fact that exception
happened. And the action is taken without inspecting its spot or cause.

In C++ at least -- what you say applies to handicapped languages like java,
lacking auto-actions in destructors.
Even there ehe mandated way is to use try/finally instead of try/catch.

> So if I wind up using a library written by someone who throws an
> exception for every incorrect condition, large or small, I have to
> handle all of them or "throw the baby out with the bath water."

The usual C++ programmer, if meat such a hostile library would probably
spend a few minutes to wrap it. And then restrict to use the wrapper that
will provide a single exception, or error codes or whatever. Hardly a big
deal. And unlikely that will be your most violent problem if the library is
really misdesigned.

But that is stuff out of your control. What worth discussion is how to shape
what you can.

> I do think they are a great way to handle an error where there is no
> elegant return path, such as a boolean return value. (Is it "yes,"
> "no," or "out of memory"?
>
> Error conditions more often represent "that didn't work, I'll try
> this" than "it's the end of the world!"

Err, WHO'll "try this"?

mike3

unread,
Jun 3, 2012, 5:58:32 PM6/3/12
to
On Jun 3, 5:55 am, Rui Maciel <rui.mac...@gmail.com> wrote:
> mike3 wrote:
> > But what if the error is not "exceptional", like an input parse error?
> > What happens if we were to use an exception because an error
> > has to propagate up several levels, but is not an "exceptional" error,
> > like a parse error?
>
> > Is it a good idea to default to exceptions for errors, and then if
> > after
> > you start actually using the code, it looks like an error code is more
> > appropriate, to use that instead?
>
> It really depends on what you define as an input parser error.  Lexers are
> designed to identify certain string patterns as specific tokens, while
> identifying everything else as a very specific token; the "unknown token"
> token.  So, stumbling on an unknown token isn't necessarily an exceptional
> event.  The same applies to grammar errors.  A set of tokens is either
> matched by your grammar or it isn't.  In some cases, a grammar might be
> defined so that a specific sequence of tokens is recognized but interpreted
> as an error.  Either way, your parser still ends up in a recognized state,
> and therefore these errors aren't exceptional situations.
>

Does this mean that we should throw on a constructor failure? E.g.
consider
if a string is passed to the constructor and the constructor parses it
to set up
the object. The parser fails, so the constructor does not know how to
get the
object into a "recognized state". Time to throw exception? Or default
the object
to some "default" state (which may be bad, as then there could be
unexpected
behavior, esp. if the input string was supplied by the user)? Or put
it in an
"error" state (which adds extra questions: what should the class
members do
if one tries them on an "error"-state object? Should they throw? If
so, then why not
just throw out of the constructor in the first place?)?

> > So does this mean the functions processing the input should return
> > error codes, with all their messy glory?
>
> That's up to whoever is in charge of designing the software.  More
> specifically, it must be decided which situation is expected and required to
> express the control flow of your program and which situation is exceptional,
> and therefore, for reasons such as clarity, it is benefitial to handle it
> separately from the main control flow.
>

So then if I get this right, "exceptional" would mean that it is
something that,
if it happens, _requires_ us to break the usual program flow, whereas
"non-
exceptional" is something that does not? So, a parse error on user
input
might not break the flow, since we can just ask the user again for
input, e.g.

---

do {
string = getInput();
parseErr = parse(parseOutput, string);
if(parseErr)
output("Bad input! Please try again.");
} while(parseErr);

---

vs. what you'd have to do with exceptions:

---

do {
string = getInput();
continueLoop = false;
try {
parse(parseOutput, string);
} catch(BadStringException e) {
output("Bad input! Please try again.");
continueLoop = true;
}
} while(continueLoop);

---

Notice how, immediately, a code smell appears: we have a "try" block
surrounding a single call. So in this case, the error code appears the
more elegant solution.

Or another example: consider taking keypresses for commands. It may
not be an exception that the user presses a key that's not a valid
command.
But if the keypress-getting routine _cannot successfully determine the
state of the keyboard_, that's probably exception and we should throw,
not return an error code.

> As an example, it's a good idea to write a lexer so that, when stumbling on
> gibberish, it returns an error code signaling just that.  By doing so, it is
> possible to set the parser to handle the not so exceptional event of parsing
> an ill-formed document, which might include the ability to throw a context-
> dependent error message or even resume parsing. This wouldn't be easy or
> simple to pull off if your lexer threw an exception when stumbling on
> gibberish.
>
> Rui Maciel

So would a good rule here be "use whichever is simplest and most
trouble-
free"? If error codes are creating trouble (proliferation of
duplicated handlers,
"error-code football", etc.), consider exceptions. If exceptions lead
to trouble
(proliferating try blocks, try blocks in loops, try blocks surrounding
single
calls, degraded performance, etc.), try error codes.

Luca Risolia

unread,
Jun 3, 2012, 6:10:05 PM6/3/12
to
On 03/06/2012 21:47, DSF wrote:
> This is the problem I have with exception handling: you CANNOT
> ignore exceptions. You must in some manner handle the possibility,
> else your program ENDS! Handling minor, recoverable, errors with
> throwing exceptions is like police shooting jaywalkers.

In fact, you should *not* use exceptions for error *recovering*. If you
want to to recover from an error, the best is to install an handler for
that purpose. If the handler fails, then throw an exception.
The couple std::set_new_handler / std::bad_alloc() is an example.

mike3

unread,
Jun 3, 2012, 6:18:49 PM6/3/12
to
On Jun 3, 7:05 am, "Balog Pal" <p...@lib.hu> wrote:
> "mike3" <mike4...@yahoo.com>
>
> >Is it a good idea to default to exceptions for errors, and then if after
> >you start actually using the code, it looks like an error code is more
> >appropriate, to use that instead?
>
> Yes. As I mentioned for some operations there's a need for both forms.
> Fortuneately it's not hard to write converters in either direction, and then
> clients can use the better-suited variant.
>

So then you _do_ need a translation layer than translates error codes
to exceptions and exceptions to error codes, and thus need a 1-to-1
correspondence between the two, with exception classes for every error
code in your error code enum (it seems that in the examples in the
C++ "bible" (Stroustrup), they have exception classes for every type
of
exception that can occur. Also, I've heard stuff about not including
type
fields in exceptions, and type fields being a bad idea in general, and
it's
better to use different classes + inheritance instead of type
fields.)?
And thus the need to update several statements in the program when
adding new errors: update the error code list and add a new exception
class and also update the translator.

So perhaps maybe I should call an exception :) to the no-type-field
rule
because it's causing gains in complexity and a reduction in
maintainability?
Then we only need to add codes to the error code list and don't need
to
mess with anything else. After all, the rule is supposed to help
maintainability,
so if you're running into a situation where it's hurting it, better to
call an
exception to the rule. Remember that programming is not based on hard
rules. Or don't bother with two-way translation, and allow for
separate and
distinct sets of error codes and exceptions.

(Why is a 1-1 correspondence needed? Because consider if the sets
are different: How do we determine what to translate to? Suppose we
have
error codes for "XPARAMOUTOFRANGE" and "YPARAMOUTOFRANGE"
but only a single "OutOfRange" exception. We can translate the codes
to exception, but how can we do the reverse translation? There's an
ambiguity.)

> >> OTOH raw input form a user/outside world can be anything, so first it
> >> must
> >> be checked/sanitized. Failure is properly expected.
> >So does this mean the functions processing the input should return
> >error codes, with all their messy glory?
>
> Don't confuse the situations and it's not that messy really.
>

What's messy is this:

---

retVal = doSomeErrorCodeReturningFunc1();
if(retVal != SUCCESS)
{
Handle it. May include a detailed response, may just "log" or
report message.
}

retVal = doSomeErrorCodeReturningFunc2();
if(retVal != SUCCESS)
{
Might do the same thing as before! Oops -- code smell: duplicated
code.
}

retVal = doSomeErrorCodeReturningFunc3();
if(retVal != SUCCESS)
{
Ditto.
}

---

And even if we have no code duplication, we may nevertheless turn
a "short method" into a "long method" -- code smell.

And this is "error-reaction logic tangled up with action logic" -- see
below.

I've got a thread going on comp.lang.c about this same thing -- where
in C, exceptions do not exist. The above seems very "Cish".

> In that layer you will have functions that return status. IsEmailValid()
> shall not throw, but return bool, or some more detailed info on the
> diagnosed problem. When you check the input you will call a ton of such
> functions, and the caller will know how to act on discrepancy.
>

No, and I would not expect such a function to throw, either. It's
after
all, a validity _checker_.

> While those functions return "error code", it is not really that from the
> function's perspective: it does all its work properly and that is the
> result.  It only becomes error code if the caller decides to not act, but
> pass it upwards.
>
> > So does this mean to prefer an exception, since then we can do "x = f() +
> > <foo>"?
>
> Yes, that is the main motivation. To separate the action logic and the
> error-reaction logic. Not mix and tangle them together.
>

So does this mean my original idea:

1. throw exceptions from functions whose return value would not be an
error
code but a useful result (or throw from constructors, since they
_can't
return anything_, and to throw from overloaded operators)

2. throw error codes from functions that would otherwise return "void"

was right?

This idea seems to suggest prefer exceptions, and not limit them to a
minority
of errors, otherwise in the majority of errors we'll be mixing
reaction logic with
action logic (see above).

> >Does this mean that we should prefer exceptions in that case, to allow it
> >to
> >propagate up to a higher level where something may be able to be done, even
> >if the error is not "exceptional"? Whereas if we can handle it on-the-spot,
> >we
> >should use an error code? E.g.
>
> By using the previously mentioned form you already admitted that the error
> condition *is* exceptional.
>
> If that invocation form is correct, it implies that
>  - involved operations are expected to succeed
>  - this spot has no interest in looking at error conditions
>
> If the code expected some problem and had alternative actions in mind for
> that condition, it would be there, wouldn't it?
>

Ah.

> >So then... "good idea to default to exceptions for errors, and then if
> >after
> >you start actually using the code, it looks like an error code is more
> >appropriate, use that instead"?
>
> Yes. Certainly don't forget to provide at least the basic exception
> guarantee, and learn about tha Abrahams principles if you didn't yet.
>

Hmm.

> >So it's OK to keep a distinct set of exceptions that's different from
> >the list of return codes?
>
> Those facilities serve some purpose. If you meet that purpose you're okay.
> Does not matter how you do that.
>
> In usual good code 95% of catch() blocks just do a conversion to some
> different exception or a return code.
>
> The rest minority that actually does something -- and it will just catch
> *any* exception (with luck the common base class for all), and just call
> .what() for a single string.
>
> And that is more than enough. Top levels only care if stuff worked or not.
> Rollback actions are issued via destructors (or simply lack of commit). The
> inforlation on the problem trigger is carried in the exception object and
> can present itself to a human-readable form so some actual intelligence,
> outside the program can figure out what next.

So then a translation layer (error codes <-> exceptions) is vital. So
what
about the problems mentioned at the beginning of this post?

Pavel

unread,
Jun 3, 2012, 6:53:31 PM6/3/12
to
Adam Skutt wrote:
> On Jun 1, 9:44 pm, Pavel
> <pauldontspamt...@removeyourself.dontspam.yahoo> wrote:
>> Stefan Ram wrote:
>>> Pavel<pauldontspamt...@removeyourself.dontspam.yahoo> writes:
>>>> I know you have already received lots of advice; but I think they omit an
>>>> important factor, namely whether you are writing a library. In my experience, I
>>>> found it quite annoying when the API of a library I use can throw.
>>
>>> And that leads to an answer to the OP's question: When in Rome do as the
>>> Romans do!
>>
>> That's what I always profess. With exceptions, however, it might be unclear
>> where's Rome and where's Athens. Just a quick example off the top of my head:
>>
>> When using STL, use std::exception hierarchy.
>> When using WFC, use System::Exception.
>> When using Qt, use return codes, but for passing errors between threads, inherit
>> your exceptions from QtConcurrent::Exception
>>
>
> You're going to have to clarify what you mean by WFC. I don't think
> it means what you think it means. If you mean the .NET runtime, then
> you can't use that in C++, so it's somewhat irrelevant. C++/CLI is
> not C++.
Interesting statement. To be considered seriously, however, it requires much
better support than a simple assertion.

>
>> When you write your own library that will most often used with WFC, often with
>> Qt and always with some STL -- how shall you expose your errors?
>>
>
> With an exception, inheriting from an STL one if you must inherit from
> one (since it is 'always' used), though your problem honestly makes
> little sense.
I do not think this statement is relevant to my point. The facts of life are:

a. C++ allows using exceptions not inherited from std::exception.
b. Many significant libraries use such exceptions.
c. Not using such libraries while writing your library or app is often not an
option.
d. Even when not using such libraries is an option in a particular case, it is
almost never wise to assume that this library or app *will never be used* with
such a library.

>
>> When you write your own library that uses WFC -- and of course STL how shall you
>> expose your library's errors and where should you catch std::exception (which
>> are fortunately rare) and guys from System::Exception hierarchy (which are much
>> more often)?
>
> In general, if you have to catch std::exception or System::Exception
> outside of the entry point of your program[1][2],
First of all, this does not make sense: the whole point of exceptions is that
you can catch them in more than one place.

Regardless, it is irrelevant: even if the above were true, it would still result
in duplicating code to implement app- or library- specific error handling policy
for STL's std::exception and other library's exceptions not derived from
std::exception.

you've done
> something pretty wrong. I think you're trying to create artificial
> problems.
Ad hominem? So far I have refrained from conveying my impression from this
discussion: that you are either in denial or have had little experience with
maintaining a useful library or application.

>
>> When you write an application that uses all 3 or even only two libraries -- what
>> errors shall you use inside your application? Many large application require
>> particular processing of particular error conditions (error logs, alarms,
>> interfaces to enterprise event handling systems, what's not) -- are you going to
>> proliferate these exceptions? Usually, you don't.
>
> Surely, write a catch block?
Oh, sure. For example, if your error processing policy requires assigning
severity level to every error before logging it, you will surely be happy to
write a catch block where the severity is best known to be assigned, won't you?

Now think where in the code this place could possibly be. A little hint:
"generally" it's not in main(), regardless of whether you are handling
std::exception or other exception (unless your app/library is so small that you
"generally" call functions from other libraries in main()).

You seem to be confusing the response to
> a condition with the condition itself,
As you are not providing any support for your statement, we should just believe
it, correct?

> but I don't see anything here
> that requires "special" handling or creates a problem.
It seems to me you cannot "see anything here" because you are carefully avoiding
actually reading my posts.

> Nevermind that
> I'm not quite sure how you'd mix the 3 libraries you mentioned in the
> first place.
Any two of them would be enough, as my post clearly said -- but you chose not to
read it before answering, correct?

>
>> The benefits of uniform error
>> processing aside, why will you want to make more parts of your code dependent on
>> the libraries only because their exceptions may penetrate them and the errors
>> are need to be processed there? What if you need to replace such a big library
>> with another monster (e.g. to port your library). How are you going to tear
>> these dependencies out?
>
> Huh? The only way I can observe an exception from a given library is
> if I'm actually calling functions within the library. As such,
> needing to handle the exception can't possibly make me more dependent
> on the library!
Yes, it can. Do you really believe that dependency on a library is a boolean
yes/no variable?

Then just wait till your business manager asks you how much time it will take to
migrate an app from library XYZ to library ABC and answer him "No" (or "Yes" if
you are a yes-man; the outcome will probably be same if he or she is an
effective manager).

You're going to need to provide an actual example of
> what you're talking about.
I already all but provided you the example of the code you will have to write to
encapsulate the dependency on exceptions and on error codes. As you chose not to
understand that, I do not have any reason to believe that providing even more
details will serve to any purpose but your attempts on nit-picking.

>
> If you're writing exception handlers to catch exceptions from
> libraries you do not call (directly or indirectly),
You really did not read my post before answering it, did you? Otherwise, how
could you possibly mistake "the library calls your application uses" for
"libraries that you do not call"?

then you're doing
> something completely and totally wrong.
then.. of course. It is so convenient to blame others for things they did not
do, isn't it?

>
>> If you are a responsible designer, you will provide your own error processing
>> layer and you will have to meticulously catch and either process or crack and
>> refactor all errors before letting them further in a thin layer wrapping the
>> library calls your application uses.
>
> No, the code that responds to an error condition really shouldn't care
> how you received the condition initially:
Sure it should even if because it syntactically has to. If you received the
condition via std::exception, you have to write "catch(...[std::]exception..)"
and if it was via AbcException that is not derived from std::exception, you have
to write catch(...AbcException..).

> if you're going to log a
> message in response to an error, the logging code doesn't care if you
> got an exception, bungled about with return codes, or just made things
> up. The same goes for displaying dialogs and just about every other
> conceivable response.
Vague "logging code" and "any other conceivable response" may not care (you like
vagueness, don't you?), but the more specific code "calling logging function" or
"filling up dialogue fields" has to care, because otherwise:

a. It won't be called at the first place, because a specific exception type
won't be caught.
b. Even if it were somehow auto-magically called, it often would not have enough
data to fill up the logging function's arguments or the dialogue fields without
cracking the exception or error code.

> The entire point of exception handling is that if you cannot (or need
> not) respond to the condition, /you pretend that it does not exist/
> [3].
I would not put it this way but, yes, the whole point of exception handling is
to facilitate handling error conditions at desired points in code. I am glad we
agree on this. I am sure you remember that I specifically stated that the
exceptions should not be thrown across library boundaries, not in general.

"Kicking can down the road" to your own code is ok. Kicking it across library
boundary is IMHO as irresponsible and morally objectionable as the
loved-by-USA-politicians kicking national debt to the next generation. Why are
you sure your library user will enjoy letting your stray std::exception to
terminate his or her program or catching it somewhere at his main() where he
only expects exceptions from his own functions or none at all?

> If you're doing something else, then you're designing your code
> entirely incorrectly. Such behavior is the height of
> irresponsibility, because it is a fool's errand.
You love denouncing actions you just made up, don't you? In conjunction with
your aptitude for kicking the can down the road, this makes me wonder: are you a
politician by any chance?

C++ libraries need
> not declare every exception they throw, so without walking every line
> of code of every library you use (directly or indirectly), one cannot
> even accomplish what you say should be done.
Exactly. Now you are at last talking about the subject of my post. If one of
your requirements is to log every error in a particular manner, it is
significantly more labor-consuming to do that "walking ever line of code" (which
you will have to do, no matter how much you hate the idea) with the
exception-based API than with error code-based API. First, the error code
dispatching is easier to formalize and then drive from configuration. Second,
error code-based error processing methods usually include some error types in
API function prototypes (as opposed to exceptions) so you will always have a hint.

It is instructive that in some libraries designed for critical applications by
serious ISPs (e.g. IBM's MQ Series C API), the error codes were returned in
output parameters. A programmer using such API does not have a chance to fully
ignore error conditions because s/he needs to define a variable (sometimes more
than one) to hold error codes. IBM's APIs are a good example because no other
company has had more experience with maintaining huge enterprise-level
applications depending on multiple libraries. It's also instructive that some
'newer-style' and best-usable POSIX C API calls have been re-designed same way
(think of strtol() that all but replaced atol()).

The above paragraph is not talking about exceptions but its subject is directly
related to the topic. Namely, if we arrange APIs error exposure design decisions
in the order from less to more prominent manifestations of possible error
condition by API functions, our order will look approximately as follows:

1. errno, GetLastError(), global variables, C++ functions without exception
specifications that throw and the likes. A programmer is not reminded about
possible error conditions in any way except possibly for the documentation.

2. C++ functions with exception specifications. A programmer is reminded about
possible error conditions if s/he has function prototype in front of him or her
while coding the call.

3. Error return codes, A programmer is reminded about error condition as in #2
plus they may be able to turn on some "unused function return value" compiler
warning or the like.

4. Errors are encoded in output parameters of API. A programmer cannot
unwillingly ignore an error condition.


>
>> The code to capture error codes is simpler,
>> shorter and faster than that needed to capture exceptions.
>
> I don't see how it can ever be less code than exception handling[4].
- It is simpler because error codes are easier tabulated for their
classification or another mapping (potentially driven by the rules that are
configured externally to the program and that are to be applied to programs in
other languages than C++) to the entities required by the application error
handling policy.

- it is shorter (especially with error-code-based or errno-based approach to
error propagation) because well-encapsulated error-checking code is notably
shorter than equally well-encapsulated try {} catch{} code. E.g. compare:

if (!handleError(apiCall(args..)))
return;

or

if (!apiCall(args..) && !handleError(errno))
return;

to

try {
apiCall(args..);
} catch(XxxException &e) {
if (!handleError(e))
throw;
}
/* if apiCall does not encapsulate exceptions from *its library's* underlying
libraries, the above code would be even longer */

- it is fater because compiler can optimize nothrow code. In a (probably futile)
attempt to prevent pointless objections to this statement I am referring you to
the Ultimate Authority of the Standard, see a footnote to 17.4.4.8-2 in ISO/IEC
14882:2003(E) or 17.6.5.12-3 in ISO/IEC 14882:2011(E) about the reason why C
library functions shall not throw:

".. This allows implementations to make performance optimizations based on the
absence of exceptions at runtime."

> At best, it can be equal, and in practice, it must necessarily be more
> because you're explicitly doing things that are done implicitly with
> exception handling.
Whom do you mean when you say "you're"? Me a library writer or me a library
user? Me a library writer is supposed to go extra mile to better serve a library
user. Me a library user will have to do more and more complex things when I use
exception-based API which my this and previous and previous-before-previous
posts explain at monotonously increasing and unnecessary for a reasonable reader
level of details.

>
>>
>> As a free bonus, you (or your user if you are the library writer) can always
>> make a choice between writing throw and nothrow functions at no coding cost.
>
> Hardly. Just returning error codes doesn't suddenly let you mark
> everything nothrow,
It allows you to "mark everything nothrow" without writing try-catch blocks.
Marking functions nothrow was not counted as part of the cost because it had to
be done regardless of the type of the underlying API if the decision to write
nothrow functions has been made.

due to the problem I mentioned above.
>
>>
>> On top of this, following the code that only calls nothrow methods is much
>> easier which increases the programmer's productivity.
>
> I fail to see how calling a method marked nothrow increases my
> productivity at all.
As the rest of the paragraph explained, in increases your productivity by
reducing the time you need to read and understand the code with only explicit
exit paths. Oh, I forgot, you are not spending much time reading code.. this "on
top of it" advantage is probably not for you then.

> It doesn't reduce what I need to be worried or
> concerned about unless the code actually provides the nothrow safety
> guarantee, which is considerably difficult.
Really? Valid C++ code that does not throw any exceptions itself and calls only
functions with an empty exception specification is guaranteed not to throw an
exception. Incidentally not throwing an exception *is* the definition of nothrow
exception safety guarantee.

>
> Merely not throwing exceptions is of very little benefit to the
> programmer.
I am not sure about that vague "merely not throwing exceptions" but exposing
only no-throw functions from a library API (which was my original and only
point) brings all the benefits I claimed.

>
>> successful real-life applications and libraries (which is equivalent to saying
>> "applications and libraries of significant size") have to spend more time on
>> reading and understanding code of others than on writing their own code.
>
> Funny, I spend more time trying to figure out what was written in all
> these technical papers I'm supposed to implement than looking at
> anyone's source code. YMMV I guess.
>
>>
>> Do your math yourself. I did mine many years ago and have never had a reason to
>> be sorry of this my application of golden rule.
>
> Unfortunately, the equation is changed, but based on what you've said
> I think you did the calculation completely incorrectly in the first
> place. Actually supporting your position with real code,which I
> strongly encourage you to do, is going to be rather difficult.
I provided more than enough use cases (and a little code snippet above, in this
post) to support my position whereas you chose to provide no use cases, let
alone the code, to support yours.

>
> Adam
>
> [1] Or the entry point to a thread or similiar concurrency construct
> [2] Though one should almost certainly 'catch(...)' in these contexts.
> [3] Handling it here includes cleaning up resources and then kicking
> the can down the road.
> [4] The occasional syntax foible aside.

-Pavel

Pavel

unread,
Jun 3, 2012, 7:07:20 PM6/3/12
to
Adam Skutt wrote:
> On Jun 3, 4:45 pm, Rui Maciel<rui.mac...@gmail.com> wrote:
>> Adam Skutt wrote:
>>> The entire point of exception handling is that if you cannot (or need
>>> not) respond to the condition, you pretend that it does not exist.
>>
>> A while ago I was working on an application that used Qt for the GUI and
>> Eigen for linear algebra. Long story short, under some circumstances Eigen
>> threw an exception and Qt caught it. And when Qt caught it, it terminated
>> the process.
>>
>> So, if you follow your own advice then you better be prepared to deal with
>> its consequences.
>
> Qt clearly says on its wrapper that it is not exception safe and has
> said so since its inception AFAIK. Broken software doesn't really
> impact my position
Reality check #1:
Good luck saying it to your manager who is asking your to fix the "broken"
software.

Reality check #2:
According to your willingness to "kick the can down the road" (that is, to
define top-level library APIs throwing exceptions), you could be an author of
that Eigen package (imagine that Eigen is perfect in all other regards so you
don't have a reason to disown it). Then, good luck attempting to sell a new
version to the Rui's company after they ask you for support on the above case
and *you tell your users that they are at fault for writing broken software and
not RTFMing on Qt*.

Sarcasm aside, products should be designed for real rather than ideal world, and
you imperfect user (who incidentally pays your bills) tends to live in the former.

> any, though I suppose I should have mentioned
> upfront that there's a depressing amount of software out there that
> lacks exception safety.
>
> Adam

-Pavel

Adam Skutt

unread,
Jun 3, 2012, 7:10:29 PM6/3/12
to
On Jun 3, 6:10 pm, Luca Risolia <luca.riso...@studio.unibo.it> wrote:
> On 03/06/2012 21:47, DSF wrote:
>
> >    This is the problem I have with exception handling: you CANNOT
> > ignore exceptions. You must in some manner handle the possibility,
> > else your program ENDS! Handling minor, recoverable, errors with
> > throwing exceptions is like police shooting jaywalkers.
>
> In fact, you should *not* use exceptions for error *recovering*.

Then what good are they?

> If you
> want to to recover from an error, the best is to install an handler for
> that purpose. If the handler fails, then throw an exception.
> The couple std::set_new_handler / std::bad_alloc() is an example.

I really don't think so. Can you imagine what std::fopen() would look
like? Before C++11, such an idea would be a nightmare. It also has
the whole "many errors are only recoverable sometimes" problem.

Regardless, I'm not sure std::set_new_handler is a good exception,
since it requires lots of handwaving and assumptions to be
effective.

Adam

Rui Maciel

unread,
Jun 3, 2012, 7:12:50 PM6/3/12
to
Adam Skutt wrote:

> Qt clearly says on its wrapper that it is not exception safe and has
> said so since its inception AFAIK.

Exception safety has nothing to do with this. Quite the opposite. This was
a case where an innocuous run-time failure, which did not caused any
relevant ill effect (IIRC it was a divide by zero problem), was made to have
consequences which greatly outweighed the nature of the problem. So, in
short, a small annoyance was needlessly turned into a serious issue just
because an exception was mishandled.


> Broken software doesn't really
> impact my position any, though I suppose I should have mentioned
> upfront that there's a depressing amount of software out there that
> lacks exception safety.

All non-trivial software is, to some extent, broken, and is bound to fail
once the right (or, better yet, wrong) conditions are met. This is the main
reason behind the need for exception handling, particularly how it provides
a way to handle any type of exception, including unpredictable and unknown
ones, and grant the programmer a simple way to either recover nicely from
them or be able to fail gracefully.

Knowing this, if you base your assertions on the idea that the code you
write isn't broken, or even that you don't use routines which are broken,
then not only are you basing your decisions on the expectation of meeting an
impossible scenario but you are also setting yourself to eventually get some
bumps and bruises somewhere in the future.


Rui Maciel


Adam Skutt

unread,
Jun 3, 2012, 7:17:45 PM6/3/12
to
On Jun 3, 7:07 pm, Pavel
<pauldontspamt...@removeyourself.dontspam.yahoo> wrote:
> Adam Skutt wrote:
> > On Jun 3, 4:45 pm, Rui Maciel<rui.mac...@gmail.com>  wrote:
> >> Adam Skutt wrote:
> >>> The entire point of exception handling is that if you cannot (or need
> >>> not) respond to the condition, you pretend that it does not exist.
>
> >> A while ago I was working on an application that used Qt for the GUI and
> >> Eigen for linear algebra.  Long story short, under some circumstances Eigen
> >> threw an exception and Qt caught it.  And when Qt caught it, it terminated
> >> the process.
>
> >> So, if you follow your own advice then you better be prepared to deal with
> >> its consequences.
>
> > Qt clearly says on its wrapper that it is not exception safe and has
> > said so since its inception AFAIK. Broken software doesn't really
> > impact my position
>
> Reality check #1:
> Good luck saying it to your manager who is asking your to fix the "broken"
> software.

Yes, I agree. If you know you're using Qt, then your design is broken
if it doesn't consider its lack of exception safety. People who
blindly mix exception-safe and unsafe code deserve what they get.

However, the mere fact that exception unsafe code exists in the world
isn't justification for avoiding exceptions, on the off possibility
someone might use your code with such broken software.

>
> Reality check #2:
> According to your willingness to "kick the can down the road" (that is, to
> define top-level library APIs throwing exceptions), you could be an author of
> that Eigen package (imagine that Eigen is perfect in all other regards so you
> don't have a reason to disown it). Then, good luck attempting to sell a new
> version to the Rui's company after they ask you for support on the above case
> and *you tell your users that they are at fault for writing broken software and
> not RTFMing on Qt*.

Except I wouldn't do that, if I was going to get paid to write
wrappers to convert the exceptions to error codes I would happily do
so. Absent pay though, it's his problem and he can keep the broken
pieces. ;)

>
> Sarcasm aside, products should be designed for real rather than ideal world, and
> you imperfect user (who incidentally pays your bills) tends to live in the former.
>

And if they want Qt support upfront then they should specify it as a
requirement. Designing for the real world does not involve
considering every last possible and framework that could interact with
my software, as such a thing is simply not possible.

Balog Pal

unread,
Jun 3, 2012, 8:01:01 PM6/3/12
to
"Pavel" <pauldont...@removeyourself.dontspam.yahoo>
> Exactly. Now you are at last talking about the subject of my post. If one
> of your requirements is to log every error in a particular manner, it is
> significantly more labor-consuming to do that "walking ever line of code"
> (which you will have to do, no matter how much you hate the idea) with the
> exception-based API than with error code-based API.

IMO&IME obsession with logging normally lurks in rotten projects, and is a
big player in the rot. Efforts could be put to write correct code instead,
and the kind that is light, focused, readable. Then it will just work. (You
can still log the few enviromental events causing exit at a central
location, and without care which operation was involved...)

But if you need something like that I still don't see why is it that hard.
I'd create a simple RAII class that you put as local at every function
entry, call its OK() at the exit. In case of unexpected exit it emits a log
line from dtor. You can simply add checkpointing or insert info on actions
you will do. I guess i could write a simple macro to automate most of the
magic. Leaving way less clutter than the retcodes version.

> It is instructive that in some libraries designed for critical
> applications by serious ISPs (e.g. IBM's MQ Series C API), the error codes
> were returned in output parameters.

That sounds weird. Can you explain why is that good? With the usual way I
can make the functions CHECKRETURN and use the compiler to flag places where
return was ignored, without extra effort. I'm not aware of similar support
on arbtrary arguments used for output.

> A programmer using such API does not have a chance to fully ignore error
> conditions because s/he needs to define a variable (sometimes more than
> one) to hold error codes.

With a C API? how hard it is to pass NULL for the output param? And even if
you force to pass a variable what makes the code look at it more than the
return code?



Adam Skutt

unread,
Jun 3, 2012, 8:02:10 PM6/3/12
to
On Jun 3, 7:12 pm, Rui Maciel <rui.mac...@gmail.com> wrote:
> Adam Skutt wrote:
> > Qt clearly says on its wrapper that it is not exception safe and has
> > said so since its inception AFAIK.
>
> Exception safety has nothing to do with this.  Quite the opposite.  This was
> a case where an innocuous run-time failure, which did not caused any
> relevant ill effect (IIRC it was a divide by zero problem), was made to have
> consequences which greatly outweighed the nature of the problem.  So, in
> short, a small annoyance was needlessly turned into a serious issue just
> because an exception was mishandled.

Exception safety has everything to do with it. If Qt were exception
safe, the exception would have been propagated upward, to where you
can handle it, and life would have continued onward. Or you would
have written your code to make sure the exception was handled before
it unwound/entered Qt.

> All non-trivial software is, to some extent, broken, and is bound to fail
> once the right (or, better yet, wrong) conditions are met. This is the main
> reason behind the need for exception handling, particularly how it provides
> a way to handle any type of exception, including unpredictable and unknown
> ones, and grant the programmer a simple way to either recover nicely from
> them or be able to fail gracefully.
>
> Knowing this, if you base your assertions on the idea that the code you
> write isn't broken, or even that you don't use routines which are broken,
> then not only are you basing your decisions on the expectation of meeting an
> impossible scenario but you are also setting yourself to eventually get some
> bumps and bruises somewhere in the future.

Ok, fine. What exactly would you propose as an alternative here? I
don't see how the consequences of your particular example are
avoidable nor any sensible alternatives. At best, you seem to be
saying, 'This won't free you from seeing bugs' but I never claimed it
would.

Broken code might do anything, including shoot daemons out your nose.
As such, it's probably not worth worrying about too heavily (unless
you know it exists) until you encounter it. I certainly don't see how
it should impact a general design principal here.

Adam

Balog Pal

unread,
Jun 3, 2012, 8:07:59 PM6/3/12
to

"Pavel" <pauldont...@removeyourself.dontspam.yahoo>

> 2. C++ functions with exception specifications. A programmer is reminded
> about possible error conditions if s/he has function prototype in front of
> him or her while coding the call.

The what? Did you read what those do in C++? Or typical rationalt to (not)
use them, ie. at Boost with cool explanation? Or at MS that just refused to
implement this braindead feature? Looking ahead in time, as in C++11 this
feature became deprecated.


It is loading more messages.
0 new messages