consensus on exceptions?

55 views
Skip to first unread message

Gabriel Zachmann

unread,
Dec 11, 2000, 2:19:48 PM12/11/00
to

I am trying to decide whether or not to use exceptions.

I searched this NG with deja
and read some GotW (http://www.peerdirect.com/resources/)
and some C++ tips (http://cpptips.hyperformix.com/Exceptions.html);
in particular http://cpptips.hyperformix.com/cpptips/except_consensus
was very informative.

But I'm afraid I still don't see if there is a consensus
whether or not
Exceptions are a Good Thing?

I found a lot of tips and discussion about the technicalities of
exceptions, but the big question is
From what I read, there seems to be a consensus that:
1. Writing exception-safe code is harder than without exceptions;
2. Excpetions introduce a second path of control flow "behind the scenes",
which increases the complexity of the code;
3. In order to do decent error-handling in constructors, you must use
exceptions.

So, my questions are:
a) should I use exceptions only for constructors and error codes for
all other methods?
b) if exceptions are used in general, should functions return *only*
error codes *or* throw exceptions? (i.e., is it ok to mix both in one
method?)
c) should exceptions be used only for "exceptional" cases, or could they
also be used for not-so-exceptional things, like bogus parameters passed
in from the caller?

All insights and pointers will be greatly appreciated.
TIA,
Gab.

--
/---------------------------------------------------------------------\
| Paradigm is a word too often used by those |
| who would like to have a new idea |
| but cannot think of one. |
| (Mervyn King, Deputy Governor, Bank of England) |
| |
| za...@igd.fhg.de g...@gab.cx Gabriel....@gmx.net |
| www.igd.fhg.de/~zach/ www.gab.cx __@/' |
\---------------------------------------------------------------------/

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Andy Watson

unread,
Dec 11, 2000, 5:37:57 PM12/11/00
to
To be honest I don't usually use them when coding. 99% of the time
one can write code that handles error coditions gracefully (how we
used to do it in the old days)..

However, I have found that many poorly designed class libraries use
them a lot. In this situation one has to catch the exceptions thrown
- MFC is a classic example of this..

The only case where they are indeed usefull is to prevent a critical
exception that may force program termination.. In this case its often
usefull to wrap the code with an exception then call your error handle
to notify the user and roll back to a stable state.

Andy


On 11 Dec 2000 14:19:48 -0500, za...@igd.fhg.de (Gabriel Zachmann)
wrote:

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Chris Uzdavinis

unread,
Dec 11, 2000, 5:42:14 PM12/11/00
to
za...@igd.fhg.de (Gabriel Zachmann) writes:

> 1. Writing exception-safe code is harder than without exceptions;

True. However, whether you like it or not, exceptions are in the
language and the WILL happen. The question is, will your code work
when they do happen?

> 2. Excpetions introduce a second path of control flow "behind the scenes",
> which increases the complexity of the code;

This path of control exiting "anywhere" already exists. Ignoring it
does not make it go away.

> 3. In order to do decent error-handling in constructors, you must use
> exceptions.

Yes, there is no other good way to indicate failure. Or, alternately,
design objects such that construction CAN'T fail. Then you don't have
to throw exceptions.



> So, my questions are:
> a) should I use exceptions only for constructors and error codes for
> all other methods?

Well, any exceptional situation where you know THAT an error occurred
but you don't know HOW to handle it is a good candidate for
exceptions.

I rarely throw them myself, but I try to write code that works if they
do happen to get thrown. This is because my code is a middleware
library, with user code calling into me, and I call back out into
them through callbacks. So they can throw exceptions and my code
really needs to continue working.

> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> method?)

It's ok to mix, but have a consistent strategy. If your functions are
internal to a subsystem, it doesn't matter how they INTERNALLY handle
errors, and error codes are fine. (Your code knows about your other
code.) Exceptions are generally better for cross-subsystem kinds of
operations, where it is someone else's code that has to handle an
error you detect. Or, if your code is seperated enough to where you
don't want part of your code to know about error codes of another part
of your application.

> c) should exceptions be used only for "exceptional" cases, or could they
> also be used for not-so-exceptional things, like bogus parameters passed
> in from the caller?

Never use them for not-so-exceptional things that can be handled
better in other ways. Bogus parameters can indeed be VERY
exceptional, it all depends on the application.

I throw an exception when I know that I've detected misuse of some
code, especially if a user is doing it. If it's my own code misusing
other parts of my code, then it's simply a bug and the assert macro is
better at finding that.

--
Chris

Alan Griffiths

unread,
Dec 12, 2000, 7:40:26 AM12/12/00
to
In article <slrn93a6ke...@schwind.igd.fhg.de>,

za...@igd.fhg.de wrote:
>
> I am trying to decide whether or not to use exceptions.
>
> I searched this NG with deja
> and read some GotW (http://www.peerdirect.com/resources/)
> and some C++ tips (http://cpptips.hyperformix.com/Exceptions.html);
> in particular http://cpptips.hyperformix.com/cpptips/except_consensus
> was very informative.

http://people.ne.mediaone.net/abrahams/abrahams.html
http://www.octopull.demon.co.uk/c++/dragons/

> But I'm afraid I still don't see if there is a consensus
> whether or not
> Exceptions are a Good Thing?
>
> I found a lot of tips and discussion about the technicalities of
> exceptions, but the big question is
> From what I read, there seems to be a consensus that:
> 1. Writing exception-safe code is harder than without exceptions;

False. Writing exception safe code is easier than equivalent code
written using return codes and conditional branches (and setjmp &
longjmp).

What is true is that it requires a different coding style that many
developers are unaware of.

> 2. Excpetions introduce a second path of control flow "behind the
scenes",

One needs to think about program state not control paths. For example,
on exit from a function (either by return or exception) the destructors
of all auto variables will have been executed.

> which increases the complexity of the code;

When using error returns the need for multiple test & branches
introduces the same number of alternative paths. But they need to be
managed manually - which increases code complexity.

> 3. In order to do decent error-handling in constructors, you must use
> exceptions.

False. In the 1980's exceptions were not in the language and idioms
were developed to accomplish this. In particular "Two Phase
Construction" - the constructor didn't do anything that could fail, and
the client code was required to call an "init()" member function before
using the object.

Avoiding exceptions increases the complexity of both implementation and
client code - but does allow "decent error-handling".

> So, my questions are:
> a) should I use exceptions only for constructors and error codes for
> all other methods?

No, use exceptions for operations that:

/1/ may fail but are expected to work (e.g. allocating resources) and
/2/ are distant from "domain" code that reacts to the failure.


> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in
one
> method?)

It is OK to mix them.

> c) should exceptions be used only for "exceptional" cases, or could
they
> also be used for not-so-exceptional things, like bogus parameters
passed
> in from the caller?

This is an edge case:

/1/ Do you want to document and test that exceptions are thrown
for "bogus parameters"?

/2/ Do you want to specify valid parameters and leave the rest as
"undefined behaviour"?

Both are valid approaches depending on your context.

> All insights and pointers will be greatly appreciated.

HTH
--
Alan Griffiths http://www.octopull.demon.co.uk/
Senior Systems Consultant, Experian tel: +44 115 968 5118
Chair, Association of C and C++ Users http://accu.org/


Sent via Deja.com http://www.deja.com/
Before you buy.

James Kanze

unread,
Dec 12, 2000, 7:47:51 AM12/12/00
to
Gabriel Zachmann wrote:

> I am trying to decide whether or not to use exceptions.

> I searched this NG with deja
> and read some GotW (http://www.peerdirect.com/resources/)
> and some C++ tips (http://cpptips.hyperformix.com/Exceptions.html);
> in particular http://cpptips.hyperformix.com/cpptips/except_consensus
> was very informative.

> But I'm afraid I still don't see if there is a consensus
> whether or not
> Exceptions are a Good Thing?

There is no concensus. Some people swear by them. Others swear at
them.

> I found a lot of tips and discussion about the technicalities of
> exceptions, but the big question is
> From what I read, there seems to be a consensus that:
> 1. Writing exception-safe code is harder than without exceptions;
> 2. Excpetions introduce a second path of control flow "behind the scenes",
> which increases the complexity of the code;
> 3. In order to do decent error-handling in constructors, you must use
> exceptions.

Add overloaded operators to 3, and you've summarized it pretty well.
On the other hand, it's possible to design constructors so they don't
fail, or so that you can check them afterwards (a la iostream), so
it's not necessarily as big a point as is sometimes pretended.

And you missed:

4. Exceptions make the main body of the function simpler, so easier to
write and to understand.

I don't think there is one true answer. Generally, I'm fairly
sceptical of exceptions, but then, I'm sceptical of unproven solutions
in general. *IF* you have a lot of cases where error detection is at
a much lower level than error handling, exceptions can simplify the
intermediate code significantly. On the other hand, they do create a
whole new family of problems involving exception safety, and the make
rigorous analysis of code flow more difficult. Which aspect weighs
heaviest will vary according to the application and the organization.

Globally, I'd say that exceptions should not be used in a critical
application, where human life is at stake. And of course, in a lot of
simple applications (compilers, etc.), they're really irrelevant -- in
exceptional cases, you just abort with an error message. For typical
server applications, etc., however, they might have a place to abort
an operation without killing the process.

> So, my questions are:
> a) should I use exceptions only for constructors and error codes for
> all other methods?

No. Be consistent.

> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> method?)

Ditto.

> c) should exceptions be used only for "exceptional" cases, or could they
> also be used for not-so-exceptional things, like bogus parameters passed
> in from the caller?

I would hope that a bogus parameter is something really exceptional,
if it comes from within my program. I wouldn't use exceptions for
errors in user input, however.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Alf P. Steinbach

unread,
Dec 12, 2000, 9:04:31 AM12/12/00
to
> I am trying to decide whether or not to use exceptions.

The only consensus of interest is then, IMO, the consensus of those
who'll maintain the code.


>...


> But I'm afraid I still don't see if there is a consensus
> whether or not
> Exceptions are a Good Thing?
>

Always depends on the application of the tool. Icepicks can
be great, although not a Good Thing as murder weapons. Of
course you mean as an error reporting mechanism, but even in
that context there's room for application and misapplication.


>...


> From what I read, there seems to be a consensus that:
> 1. Writing exception-safe code is harder than without exceptions;

Meaningless or false.

(1) If there can be no exceptions, then the code is exception-safe.

(2) Otherwise, you *need* exception handling in order to make the
code exception safe.

(3) With a more general interpretation, writing "error safe" code
is distinctly easier using exception handling (that's the
whole point of the mechanism).


> 2. Excpetions introduce a second path of control flow "behind the
scenes", which increases the complexity of the code;

First part is true, conclusion is generally false. Generally the
complexity of the code is lowered because you can separate error
handling from normal case code, and because you don't have to
clutter the code with return value checking. Otoh. it's *possible*
to increase the actual complexity of the code by lowering the
apparent complexity, e.g. code that is structured to function
correctly in the presence of exceptions but only because things
get done in a certain order, and where this isn't documented.


> 3. In order to do decent error-handling in constructors, you must
> use exceptions.

Generally this is false, but exceptions are way more convenient
for this than other means (e.g. two-phase construction with Init
method, reference error parameter or ditto global, error handling
function, whatever). What you do gain is automatic deallocation,
plus -- depending on the alternative considered -- removal of the
possibility of using a non-properly constructed object. These
advantages are so great that you'd need a very good reason *not*
to use exceptions for error reporting from constructors (one such
reason being the deallocation bug of Visual C++ 5.0 and earlier).


> ...


> a) should I use exceptions only for constructors and error codes for
> all other methods?

No. But that doesn't imply the opposite, that you should always use
exceptions. Use sound judgement, considering always how your classes
will or may be used. This call can be tough, since there is a
"conflict of interest" present. At the lowest levels of the code
where failures often occur, efficiency dictates return codes or some
such scheme, while correctness guarantees dictates using exceptions
(essentially this boils down to the guarantees you endowe your
methods with; one solution is to have one set of "bare" error-code
based functions and one set of "safe" exception-throwing wrappers).


> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in
> one method?)

Don't mix error reporting strategies. But you can use return codes
for success reporting. Again, this boils down to the contracts you
define for the methods, and designing those contracts can be hard.


> c) should exceptions be used only for "exceptional" cases, or could
> they also be used for not-so-exceptional things, like bogus
> parameters passed in from the caller?

First is easy: yes. Second part is false: bogus parameters *are* (or
at least, should be) exceptional. I'd use exceptions for that.

Hth.,

- Alf


--
alf_DOT_steinbach_AT_ac_DOT_com (clean the address before replying)


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Robert J. Hansen

unread,
Dec 12, 2000, 9:05:19 AM12/12/00
to
> I am trying to decide whether or not to use exceptions.

Don't think of exceptions as being error handling constructs; think of them
as program flow constructs. Just like a goto isn't automatically harmful or
beneficial in C, using exceptions isn't automatically good one way or
another in C++.

> 1. Writing exception-safe code is harder than without exceptions;

Untrue. Writing exceptionless code requires that you introduce
functionality to handle exceptional states. One way or another, exception
conditions occur and you'd better be equipped to handle them. If you don't
like how new throws an exception on a bad memory allocation, you're free to
use new(nothrow), but you'd better check for NULL after every allocation.

See what I mean? One way or another, error conditions must be checked for.
Exceptions are oftentimes an elegant way to check for, and handle, these
error states.

> 2. Excpetions introduce a second path of control flow "behind the scenes",
> which increases the complexity of the code;

No. They change a second path of control flow, not add a new one. The
original second path starts at an error state and leads straight to a
coredump. With error handling (which may include exceptions as part of an
intelligent error design), this catastrophic execution path can be
redirected to a more graceful exit, or even have termination avoided
altogether.

> 3. In order to do decent error-handling in constructors, you must use
> exceptions.

Not necessarily. Consider:

class A
{
public:
int errorstate;
A(void)
{
errorstate = 0;
// do more stuff here, traps an error
errorstate = 1; return;
// do more stuff here if no error trapped
}
};

int main(int argc, char *argv[])
{
A myfunc;
if (myfunc.errorstate) { // do error handling stuff here
}

Note that I don't recommend doing things this way. But it does show that
it's possible to do error handling in constructors without exceptions (even
if it means just flagging a failure appropriately).

> a) should I use exceptions only for constructors and error codes for
> all other methods?

Use them whenever they're appropriate. How will you know if they're
appropriate? By using your experience. So get out and experiment around
with exceptions some. :)

> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> method?)

Just be consistent. If you do one, then only do that one. If you do both,
then always do both. Etc.

> c) should exceptions be used only for "exceptional" cases, or could they
> also be used for not-so-exceptional things, like bogus parameters
passed
> in from the caller?

Exceptions are not only useful for errors. Consider:

if (...)
{
if (...)
{
if (...)
{
if (...) throw myException();
// insert multiple closing brackets here

catch (myException &e)
{
.... etc.
}


.... In that above case, exceptions work as a better GOTO. Remember:
exceptions /are just program control statements/. They aren't magically
tied to error conditions.

Adrian Edmonds

unread,
Dec 12, 2000, 11:51:57 AM12/12/00
to

"Gabriel Zachmann" <za...@igd.fhg.de> wrote in message
news:slrn93a6ke...@schwind.igd.fhg.de...
>
<snip>

> So, my questions are:
> a) should I use exceptions only for constructors and error codes for
> all other methods?
> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> method?)
> c) should exceptions be used only for "exceptional" cases, or could they
> also be used for not-so-exceptional things, like bogus parameters
passed
> in from the caller?
>
IMHO

a) no
b) no. Use error codes for run of the mill errors and exceptions for
catastrophic failures
c) I agree with the first part

Adrian

P.S Your sig is too long.

James Kanze

unread,
Dec 12, 2000, 11:52:33 AM12/12/00
to
Chris Uzdavinis wrote:

> za...@igd.fhg.de (Gabriel Zachmann) writes:

> > 1. Writing exception-safe code is harder than without exceptions;

> True. However, whether you like it or not, exceptions are in the
> language and the WILL happen. The question is, will your code work
> when they do happen?

That's not really true. The language supports exceptions, but it
certainly doesn't require their use. The standard library only throws
exceptions in a few specific cases, which it is possible to avoid.

> > 2. Excpetions introduce a second path of control flow "behind the scenes",
> > which increases the complexity of the code;

> This path of control exiting "anywhere" already exists. Ignoring it
> does not make it go away.

It doesn't exist in most of the code I write.

> > 3. In order to do decent error-handling in constructors, you must use
> > exceptions.

> Yes, there is no other good way to indicate failure. Or,
> alternately, design objects such that construction CAN'T fail. Then
> you don't have to throw exceptions.

Designing constructors so they can't fail is often a good idea anyway.

> > So, my questions are:
> > a) should I use exceptions only for constructors and error codes for
> > all other methods?

> Well, any exceptional situation where you know THAT an error occurred
> but you don't know HOW to handle it is a good candidate for
> exceptions.

> I rarely throw them myself, but I try to write code that works if
> they do happen to get thrown. This is because my code is a
> middleware library, with user code calling into me, and I call back
> out into them through callbacks. So they can throw exceptions and
> my code really needs to continue working.

In general, writing exception safe code is probably a good idea.
Because even if you don't use exceptions today, you might want to in
the future.

> > b) if exceptions are used in general, should functions return *only*
> > error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> > method?)

> It's ok to mix, but have a consistent strategy. If your functions
> are internal to a subsystem, it doesn't matter how they INTERNALLY
> handle errors, and error codes are fine. (Your code knows about
> your other code.) Exceptions are generally better for
> cross-subsystem kinds of operations, where it is someone else's code
> that has to handle an error you detect. Or, if your code is
> seperated enough to where you don't want part of your code to know
> about error codes of another part of your application.

> > c) should exceptions be used only for "exceptional" cases, or could they
> > also be used for not-so-exceptional things, like bogus parameters
passed
> > in from the caller?

> Never use them for not-so-exceptional things that can be handled
> better in other ways. Bogus parameters can indeed be VERY
> exceptional, it all depends on the application.

> I throw an exception when I know that I've detected misuse of some
> code, especially if a user is doing it. If it's my own code
> misusing other parts of my code, then it's simply a bug and the
> assert macro is better at finding that.

It depends a lot on the application.

Ideally, you'd probably like to cut the application up into a lot of
little processes, so that an error in one (e.g. a bad pointer) can't
propagate back into the others. If you do this, you're "exception"
mechanism is called abort with an error message:-). In many cases,
however, the price for doing this is too high. So you use exceptions
for aborting what you'd really like to have in a separate process.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Mark Wilden

unread,
Dec 12, 2000, 3:27:11 PM12/12/00
to
"James Kanze" <James...@dresdner-bank.com> wrote in message
news:3A3612BC...@dresdner-bank.com...

>
> Designing constructors so they can't fail is often a good idea anyway.

Interesting statement. Clearly, designing _anything_ so it can't fail is a good
idea. However, how does one manage this with constructors in particular? How
does one design a constructor so that it doesn't care if the machine is out of
memory, or if a needed file doesn't exist? The only answer is to push all that
off onto another function that the client has to call. But what does that buy?

I guess I'd like more explanation of your statement.

Francis Glassborow

unread,
Dec 12, 2000, 3:37:23 PM12/12/00
to
In article <3A361160...@dresdner-bank.com>, James Kanze
<James...@dresdner-bank.com> writes

>Globally, I'd say that exceptions should not be used in a critical
>application, where human life is at stake. And of course, in a lot of
>simple applications (compilers, etc.), they're really irrelevant -- in
>exceptional cases, you just abort with an error message. For typical
>server applications, etc., however, they might have a place to abort
>an operation without killing the process.

Even if you choose never to use exceptions yourself, I think it is
advisable to write exception safe code.

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Walt Howard

unread,
Dec 12, 2000, 5:52:00 PM12/12/00
to
"Mark Wilden" <ma...@pagm.com> writes:

> "James Kanze" <James...@dresdner-bank.com> wrote in message
> news:3A3612BC...@dresdner-bank.com...
> >
> > Designing constructors so they can't fail is often a good idea anyway.
>
> Interesting statement. Clearly, designing _anything_ so it can't fail is a
good
> idea. However, how does one manage this with constructors in particular? How
> does one design a constructor so that it doesn't care if the machine is out
of
> memory, or if a needed file doesn't exist? The only answer is to push all
that
> off onto another function that the client has to call. But what does that
buy?

Easy.

Have the constructor do nothing.

Constructor()
{
}

Then have an Init() function that does the actual initialization.

You asked.

It buys a big plus in some situations, delayed activation. Sometimes
you are in situations where creation of temporaries is inevitable, for
example, sticking something into an STL collection. In those cases,
you like to have a lightweight constructor that doesn't actually do
anything, for example, a file object that doesn't actually open the
file, otherwise, even the creation of a temporary is going to open a
file, destruction of the temporary will close it. Very wasteful,
especially for disk access or network access. Imagine a
"SocketConnection" class that, for every temporary, had to actually go
out and contact the remote host.

Walt Howard

Walt Howard

unread,
Dec 12, 2000, 6:34:36 PM12/12/00
to
Even if you don't use exceptions, even one exception in your entire
program or library you are using, causes the compiler to construct the
proper stack frames. You are paying the cost anyway.

I think people should give a "no error code" program a try. Go all the
way. Never have your functions return error codes, always have them
throw an exception if they fail in their task. Really give exceptions
a fair shot.

Then, when you've made a program work that way, you can decide which
is really best, exceptions or error return codes. Until then, you are
really just guessing.

Walt Howard

Francis Glassborow <francis.g...@ntlworld.com> writes:

> In article <3A361160...@dresdner-bank.com>, James Kanze
> <James...@dresdner-bank.com> writes
> >Globally, I'd say that exceptions should not be used in a critical
> >application, where human life is at stake. And of course, in a lot of
> >simple applications (compilers, etc.), they're really irrelevant -- in
> >exceptional cases, you just abort with an error message. For typical
> >server applications, etc., however, they might have a place to abort
> >an operation without killing the process.
>
> Even if you choose never to use exceptions yourself, I think it is
> advisable to write exception safe code.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Mark Wilden

unread,
Dec 12, 2000, 9:07:37 PM12/12/00
to
"Walt Howard" <wa...@wallyware.com> wrote in message
news:wksnntn...@wallyware.com...

>
> Then, when you've made a program work that way, you can decide which
> is really best, exceptions or error return codes. Until then, you are
> really just guessing.

I'm learning COM right now. COM objects always return error codes. This in
itself was interesting; I'm not used to returning a result code from a function
that can only succeed, but it's nice and consistent.

The client of that COM object uses #import to call those COM methods. #import
sets things up so that if any method of the COM object fails, it throws an
exception. So COM clients (who use #import) must get used to the "all-exception"
approach.

I do like "all-exception", however, I'd point out that even "all-error codes" is
different than the way I'm used to programming.

Chris Uzdavinis

unread,
Dec 12, 2000, 9:09:59 PM12/12/00
to
Walt Howard <wa...@wallyware.com> writes:

> Easy.
>
> Have the constructor do nothing.
>
> Constructor()
> {
> }

> Then have an Init() function that does the actual initialization.

It's not always easy, only with trivial objects, or with objects that
hold objects that are guaranteed not to themselves throw exceptions.

Take your class above and make it have a data member (not a pointer)
of type Blow_Up and try to make a constructor that doesn't throw:

class Blow_Up
{
public:
Blow_Up() { throw 1; }
};


class A
{
public:
A()
{
// Q: how to implement such that construction doesn't fail?
}

private:
Blow_Up t;
};


--
Chris

Jeff Connelly

unread,
Dec 12, 2000, 10:03:04 PM12/12/00
to
> So, my questions are:
> a) should I use exceptions only for constructors and error codes for
> all other methods?

I think the benefits of exceptions outweigh any complexities involved,
and exceptions should replace error codes in general (with, um, a
few "exceptions")

> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in
one
> method?)

It's OK to mix, but IMO not as a general strategy. You might decide to
do certain sets of conditions with return codes, and certain sets of
conditions with exceptions. See below.

> c) should exceptions be used only for "exceptional" cases, or could
they
> also be used for not-so-exceptional things, like bogus parameters
passed
> in from the caller?

It depends - how bad are bogus parameters? For example, if you can do
some reasonable default behavior if you get a bad parameter that
wouldn't surprise the use, then maybe no exception is needed. The
general guideline is to use exceptions when you cannot do, or finish,
what you were asked to do, and don't use exceptions to do more than
that.

--
Regards,
Jeff


Sent via Deja.com
http://www.deja.com/

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Mark Wilden

unread,
Dec 12, 2000, 10:03:53 PM12/12/00
to
"Walt Howard" <wa...@wallyware.com> wrote in message
news:wkvgspn...@wallyware.com...

> "Mark Wilden" <ma...@pagm.com> writes:
>
> > "James Kanze" <James...@dresdner-bank.com> wrote in message
> > news:3A3612BC...@dresdner-bank.com...
> > >
> > > Designing constructors so they can't fail is often a good idea anyway.
> >
> > Interesting statement. Clearly, designing _anything_ so it can't fail is a
> good
> > idea. However, how does one manage this with constructors in particular?
How
> > does one design a constructor so that it doesn't care if the machine is
out
> of
> > memory, or if a needed file doesn't exist? The only answer is to push all
> that
> > off onto another function that the client has to call. But what does that
> buy?
>
> It buys a big plus in some situations, delayed activation.

Sorry, I was asking with respect to exceptions. I'm aware of other advantages
(and disadvantages) of this technique, but wanted to know how they relate to
constructor failure.

James Kanze

unread,
Dec 13, 2000, 10:01:28 AM12/13/00
to
Mark Wilden wrote:
>
> "James Kanze" <James...@dresdner-bank.com> wrote in message
> news:3A3612BC...@dresdner-bank.com...

> > Designing constructors so they can't fail is often a good idea
> > anyway.

> Interesting statement. Clearly, designing _anything_ so it can't
> fail is a good idea. However, how does one manage this with
> constructors in particular? How does one design a constructor so
> that it doesn't care if the machine is out of memory, or if a needed
> file doesn't exist? The only answer is to push all that off onto
> another function that the client has to call. But what does that
> buy?

It means that you don't have to deal with exceptions coming from that
constructor. If you defer anything that can fail to a later
initialize function, you can handle a return code. If you use a
factory, you can delete the object if the initialization fails, and
return a null pointer. If on the other hand, you use an internal
failure flag, like iostream, you can integrate the error handling into
that of the normal case, again like iostream.

Globally, making it an absolute rule not to throw from a constructor
only makes sense (to me) if you are designing to not use exceptions
anywhere. But even in constructors, exceptions should only be used
for exceptional cases, so you will occasionally have cases where other
mechanisms are needed anyway.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Albrecht Fritzsche

unread,
Dec 13, 2000, 10:03:09 AM12/13/00
to
Mark Wilden wrote:
>
> However, how does one manage this with constructors in particular?
> How does one design a constructor so that it doesn't care if the
> machine is out of memory, or if a needed file doesn't exist?

What about a constructor like

struct X{
X() { try { Init(); /* ... */ } catch(...){} }
void Init() { /* ... */}
};

I am starting to respect exception safety more and more and am
reasoning about those problems either.

Ali
--
Albrecht Fritzsche, Software Developer
alfabet meta-modelling ag,
leibnitzstr. 53, 10629 berlin, germany
http://www.alfabet.de

James Kanze

unread,
Dec 13, 2000, 10:04:18 AM12/13/00
to
Alan Griffiths wrote:

> > From what I read, there seems to be a consensus that:
> > 1. Writing exception-safe code is harder than without exceptions;

> False. Writing exception safe code is easier than equivalent code
> written using return codes and conditional branches (and setjmp &
> longjmp).

It's certainly false that this is a consensus opinion. Whether
writing robust exception safe code is easier or is harder than the
alternatives is very much a personal matter. I've been writing robust
error handling code for over twenty years now, and I don't see where
exceptions make my life easier. But that could at least in part be
because I've ingrained habits which make the alternatives particularly
easy. Or it could be because I've mainly worked on critical systems,
where correct error handling is considered a fundamental part of the
basic algorithm (and the algorithms are generally fundamentally pretty
simple, so the added complexity due to error handling doesn't render
them unmanageable).

> What is true is that it requires a different coding style that many
> developers are unaware of.

> > 2. Excpetions introduce a second path of control flow "behind the
> scenes",

> One needs to think about program state not control paths. For
> example, on exit from a function (either by return or exception) the
> destructors of all auto variables will have been executed.

The problem is that there is very little theoretical work to support
program proofs based purely on program state, without regards to
control paths.

> > which increases the complexity of the code;

> When using error returns the need for multiple test & branches
> introduces the same number of alternative paths. But they need to
> be managed manually - which increases code complexity.

The number may actually be significantly less in practice. You always
know when a component returns a return code; you may often not know in
the case of exceptions, and you must be prepared to handle the worst
case.

> > 3. In order to do decent error-handling in constructors, you must use
> > exceptions.

> False. In the 1980's exceptions were not in the language and idioms
> were developed to accomplish this. In particular "Two Phase
> Construction" - the constructor didn't do anything that could fail,
> and the client code was required to call an "init()" member function
> before using the object.

> Avoiding exceptions increases the complexity of both implementation
> and client code - but does allow "decent error-handling".

> > So, my questions are:
> > a) should I use exceptions only for constructors and error codes for
> > all other methods?

> No, use exceptions for operations that:

> /1/ may fail but are expected to work (e.g. allocating resources) and
> /2/ are distant from "domain" code that reacts to the failure.

Right. Basically, if the error is such that you can recover and
continue, exceptions are probably not the correct answer. If the
error will almost certainly result in aborting the current operation,
then exceptions can be considered.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Wil Evers

unread,
Dec 13, 2000, 10:23:43 AM12/13/00
to
In article <3A361160...@dresdner-bank.com>, James Kanze wrote:

> Gabriel Zachmann wrote:

[snippage]



> > c) should exceptions be used only for "exceptional" cases, or
> > could they also be used for not-so-exceptional things, like
> > bogus parameters passed in from the caller?
>
> I would hope that a bogus parameter is something really exceptional,
> if it comes from within my program. I wouldn't use exceptions for
> errors in user input, however.

I would say that a bogus parameter is probably too exceptional to
handled by an exception.

The problem with throwing an exception when a programming error is
detected is that at some higher level, the exception may be caught
and then considered handled, while nothing has been done to fix the
error that caused the exception.

Rather then letting the program muddle on, I believe it is usually
better to have it log as much error information as possible and then
abort, leaving it up to whatever/whoever invoked it to take
appropriate action.

- Wil

--
Wil Evers, DOOSYS IT Consultants, Maarssen, Holland
[Wil underscore Evers at doosys dot com]

Mark Wilden

unread,
Dec 13, 2000, 4:06:27 PM12/13/00
to
"James Kanze" <James...@dresdner-bank.com> wrote in message
news:3A376900...@dresdner-bank.com...
>
> [An Init method] It means that you don't have to deal with exceptions coming

from that
> constructor. If you defer anything that can fail to a later
> initialize function, you can handle a return code.

But I wouldn't regard this as an advantage, as I believe failures should be
handled via the exception mechanism.

> If you use a
> factory, you can delete the object if the initialization fails, and
> return a null pointer.

If the failure comes from the constructor, there is no need to delete the
object, of course.

> If on the other hand, you use an internal
> failure flag, like iostream, you can integrate the error handling into
> that of the normal case, again like iostream.

True...that's never especially appealed to me, though.

> Globally, making it an absolute rule not to throw from a constructor
> only makes sense (to me) if you are designing to not use exceptions
> anywhere.

Agreed.

But even in constructors, exceptions should only be used
> for exceptional cases, so you will occasionally have cases where other
> mechanisms are needed anyway.

Guess I'd have to see a specific case.

Mark Wilden

unread,
Dec 13, 2000, 4:08:30 PM12/13/00
to
"Wil Evers" <bou...@dev.null> wrote in message
news:jhi519...@tinus.intra.doosys.com...

> In article <3A361160...@dresdner-bank.com>, James Kanze wrote:
>
> Rather then letting the program muddle on, I believe it is usually
> better to have it log as much error information as possible and then
> abort, leaving it up to whatever/whoever invoked it to take
> appropriate action.

Repeat after me: It all depends on the program.

Every program will have different costs and benefits of "muddling on". If the
cost is low enough (the program can't do much harm--it's not guiding missiles or
anything) and/or the benefit is high enough (by not aborting, you at least give
the user the chance to save her work), then muddling on is appropriate.

Herb Sutter

unread,
Dec 13, 2000, 4:09:13 PM12/13/00
to
James Kanze <James...@dresdner-bank.com> writes:
>exceptions should only be used for exceptional cases

This is a commonly-repeated (I used to say it too) but fuzzy statement. Its
main problem, borne out in many newsgroup discussions, is that what's "truly
exceptional" is subjective and hasn't so far been a reliable guide. Some
think it means hard errors where the system is going to crash anyway. Others
think it also includes serious errors where a major operation can't be
completed. Still others think it means when any operation, large or small,
can't be completed. A few people would even include "success with info"
warnings, meaning anything beyond "OK, done" would be an exception -- to
them, anything short of clear success is to them an "exceptional case."

So my question is: What does "exceptional cases" mean to you? Can you give a
clear and rigorous definition that can be used to make decisions about new
cases? If so, I can take the definition and apply it to some cases and see
whether or not I agree with it -- and, more importantly, why or why not.
Again, in fairness, I used to say the same thing, and after a several
muddled attempts over time I realized I was guilty of fuzzy thinking because
I couldn't decide on a clear and unambiguous definition.

I've finally come around to Dave Abrahams' view:

Exceptions are basically just glorified return codes
with different semantics,

the main semantic differences being that exceptions: a) can't be ignored; b)
don't have to be manually propagated up to a suitable handler; and c)
require some more care in intermediate code so that stack unwinding is safe.
The first two are clear advantages; the last is now (finally)
well-understood but does require extra coding discipline and will continue
to be a source of articles and talks and maybe even some new analysis about
cases not yet discovered/covered (although it's widely believed that the
area is indeed now sufficiently well covered to declare it "well-understood"
as I just did).

Let me float an idea and see what comes out: A lot of people lump the choice
of exceptions vs. return codes into the error handling strategy, but I think
it's useful to distinguish between the mechanism and the strategy. That is,
choices about error handling strategy (what errors to detect/report, and
what/where to correct them) could be orthogonal to the reporting method (the
middle piece, what mechanism to use to report them); together, both would
form the error handling policy. Comments? Reactions?

Herb

---
Herb Sutter (mailto:hsu...@peerdirect.com)

CTO, PeerDirect Inc. (http://www.peerdirect.com)
Contributing Editor, C/C++ Users Journal (http://www.cuj.com)

Kevin Cline

unread,
Dec 13, 2000, 4:41:04 PM12/13/00
to
Walt Howard wrote:

> Easy.
>
> Have the constructor do nothing.
>
> Constructor()
> {
> }
>
> Then have an Init() function that does the actual initialization.
>
> You asked.
>

> It buys a big plus in some situations, delayed activation...

But this idiom introduces a completely new kind of error -- attempts to access an
uninitialized object.
Does every member function test to make sure the object has been initialized?
That's a lot of clutter in the code. Or do you just allow the use of
uninitialized objects to eventually cause a crash?

Mark Wilden

unread,
Dec 13, 2000, 5:30:08 PM12/13/00
to
"Albrecht Fritzsche" <albrecht....@alfabet.de> wrote in message
news:3A37724C...@alfabet.de...

>
> What about a constructor like
>
> struct X{
> X() { try { Init(); /* ... */ } catch(...){} }
> void Init() { /* ... */}
> };

Well, I guess that's another approach to this issue: Have Init() throw an
exception, which the constructor then ignores. :)

Sorry, I don't see how this would be a solution.

Mark Wilden

unread,
Dec 13, 2000, 10:25:33 PM12/13/00
to
"Herb Sutter" <hsu...@peerdirect.com> wrote in message
news:ok8f3t8ia3s49k7jj...@4ax.com...

>
> I've finally come around to Dave Abrahams' view:
>
> Exceptions are basically just glorified return codes with different
semantics

Not sure what Dave means by "different semantics". That's the trouble with
that
bloody word: what's the semantics of "semantics"? :)

In any case, return codes that indicate success clearly would not be replaced
by
exceptions.

Mark Wilden

unread,
Dec 14, 2000, 8:48:34 AM12/14/00
to
"Kevin Cline" <kcl...@mayannetworks.com> wrote in message
news:3A37BF13...@mayannetworks.com...

> Does every member function test to make sure the object has been
initialized?
> That's a lot of clutter in the code.

It's not so bad. In my COM work (where two-stage init is required, at least as
far as I can see), I just have a macro (!) that checks the state and throws an
exception, if nec.--one line of code.

Francis Glassborow

unread,
Dec 14, 2000, 8:49:28 AM12/14/00
to
In article <ok8f3t8ia3s49k7jj...@4ax.com>, Herb Sutter
<hsu...@peerdirect.com> writes

>Let me float an idea and see what comes out: A lot of people lump the choice
>of exceptions vs. return codes into the error handling strategy, but I think
>it's useful to distinguish between the mechanism and the strategy. That is,
>choices about error handling strategy (what errors to detect/report, and
>what/where to correct them) could be orthogonal to the reporting method (the
>middle piece, what mechanism to use to report them); together, both would
>form the error handling policy. Comments? Reactions?

There are at least four ways of handling errors (exceptions).

1) Set a global variable and trust that it will be checked. I recently
asked a dozen attendees at on an Advanced C++ Development techniques
course to raise their hands if they had ever checked errno. I was
surprised that two actually claimed to have done so.

2) Use a handler - callback function - appropriate for a local fix and
immediate retry (e.g. out of memory, printer problems etc.)

3) Use some form of error return, useful if you expect that the calling
function can fix the problem, and if it does not, nothing terrible will
happen if it is ignored.

4) Throw an exception - useful if you expect that a possibly remote
function on the call stack will handle it. Also useful if the problem
must not be ignored.

Note that none of these classify problems as 'exceptional' just how they
are best handled. In general 2, 3 and 4 are useful. 1 can be used but
only if the error is non-fatal.

BTW I normally throw endofprogram (which I routinely catch in main() )
to ensure cleanup when ending anywhere other than in main()


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Matthew Collett

unread,
Dec 14, 2000, 8:52:06 AM12/14/00
to
Herb Sutter <hsu...@peerdirect.com> wrote:

>James Kanze <James...@dresdner-bank.com> writes:
>>exceptions should only be used for exceptional cases
>
>This is a commonly-repeated (I used to say it too) but fuzzy statement.
>

>So my question is: What does "exceptional cases" mean to you?
>

>Herb

In principle: an exception occurs when a function cannot satisfy its
stated or implied post-conditions even though the caller met its
pre-conditions.

In practice, this is to some extent circular, since the definition of
the post-conditions will depend on how errors are going to be reported.

Best wishes,
Matthew Collett

--
The word "reality" is generally used with the intention of evoking sentiment.
-- Arthur Eddington

Walt Howard

unread,
Dec 14, 2000, 11:29:43 AM12/14/00
to
> James Kanze <James...@dresdner-bank.com> writes:
> >exceptions should only be used for exceptional cases
>
> This is a commonly-repeated (I used to say it too) but fuzzy statement. Its
> main problem, borne out in many newsgroup discussions, is that what's "truly
> exceptional" is subjective and hasn't so far been a reliable guide. Some
> think it means hard errors where the system is going to crash anyway. Others
> think it also includes serious errors where a major operation can't be
> completed. Still others think it means when any operation, large or small,
> can't be completed. A few people would even include "success with info"
> warnings, meaning anything beyond "OK, done" would be an exception -- to
> them, anything short of clear success is to them an "exceptional case."
>
> So my question is: What does "exceptional cases" mean to you? Can you give a
> clear and rigorous definition that can be used to make decisions about new
> cases? If so, I can take the definition and apply it to some cases and see
> whether or not I agree with it -- and, more importantly, why or why not.
> Again, in fairness, I used to say the same thing, and after a several
> muddled attempts over time I realized I was guilty of fuzzy thinking because
> I couldn't decide on a clear and unambiguous definition.

Ditto, but in forcing myself to use exceptions I've had to create a
sharp razor criterium to decide, "use exceptions or not"? Right or
wrong, I've decided this:

For me, exception means, "that which the current context is not
prepared to deal with". That's pretty good but now and then I still
can't make the decision clearly. For example, a find() function. Is
failure to find what you are looking for, an exception? It
depends. The concept of "find" means you don't have it and might not
have it ever, otherwise you'd call it get(). If lots of failures are
reasonably expected as part of a normal run, it isn't. But, once
again, what do the words "reasonably" and "normal" mean?

By context I mostly mean function, but it can mean more. By this
definition, if you write an openfile function, and can't open the file
you have two choices: figure out how to fix the problem, right then
and there, or throw an exception.

When you code there is probably a main flow of control that you are
trying to accomplish, i.e., openfile, readwrite, closefile. If at any
point you are unable to proceed, that is an exception. Errors are like
the garbage in a program. When you are working furiously on a work of
art, for example a sculpture, you keep your attention on the creation,
on the intended result, not on the bits of clay that fall onto the
floor. Catch clauses are like the broom you use to sweep up the
garbage after your marvelous creation is done. In some ways, that
isn't a good analogy. In a computer program, some of the bits of clay
are fatal errors!

Why errorcodes suck.

1) your function must assume that the calling function understands its
error codes. If this is to happen your function, and the caller are
forever mutually dependent which lessens their generic use and
reuseabilty.

2) You can only return a small amount of information, usually a
number. This is often insufficient to correct the error. For example,
your fileopen function fails and returns an error 5, Access
denied. Great, no problema. Wouldn't it be nice to know which filename
failed? You say, "That's stupid! The calling function knows which
filename it used!". Are you sure? Maybe that's why the fileopen
failed, you weren't using the right filename to begin with. In fact
I'd be willing to be that 99% of failed opens are caused by wrong
filename.

3) error codes pervert the entire notion of a function. A strict
mathematical function is supposed to take input of certain parameters
and return only one value. We don't have to subscribe to strict math
just for the sake of it, but here is a consequence of that.

Code written using exceptions:
-----------------------------

String data = file.readline( DESIRED_LENGTH );

Code written without exceptions:
-------------------------------

String data;
char buffer[1024];
int rval = file.readline( buffer, sizeof(buffer));
if ( rval != error )
{
data = buffer;
return NO_ERROR;
}
else
return rval;

And so on. Even the function that called this has to check errorcodes!
The contamination spreads throughout the entire program. We've been
living for so long, accepting this as normal that few are questioning
it anymore. Error return codes are a hack!

7 times as many lines. Why? Because ideally, a function can be
inserted where a data item is wanted because it can be trusted to
return a value that fits the context. If you are using errorcodes, you
have to check to make sure the return value isn't the error value
before using it in the context.

You might say, "Yes, but at some point you must pay the piper and
catch those exceptions. Ha Ha! Where are you now Mr. Exception?"

Well I'd say, yes, I do, but errorcode handling requires paying the
piper anyway in every function. Using exceptions let's me deal with
the errors where I want to.

4) Error codes are left unchecked - This can be accidental on purpose,
or more likely, "so yeah, I got an error, what the hell do I do with
it now? I wrote this function to return a string, do I have to rewrite
the thing now? Screw it, I'll just print an error and abort, or just
log the error, or just ignore it altogether.

When I first tried exceptions I was skeptical but I forced myself to
do it and gradually, the light went on in my head. I did it because I
thought programmers around the world would be turning to this new
technology and I didn't want to become a dinosaur. I was wrong. Every
big shop I contracted in didn't use exceptions. I think this has three
main causes:

1) Intellectual Inertia. Programmers have each developed ways to code
that for them, are dependable and predictable. You need to really do
an entire program using only exceptions. In the Linux world, I've yet
to see an open source project that uses exceptions and darn few that
even use C++. So all the examples that are out there for new
programmers are using the old style error codes. You have to take it
upon yourself to give exceptions a try because it doesn't seem like
anyone else is going to do it. Programmers are the most suspicious
people in the world when it comes to new technologies. I'm sure that
behind that attitude is an incident of pure intellectual hell where
they tried something new and it ended up costing them evenings and
weekends debugging. I know that's what it is for me. Trying a new
technology, especially on an already overloaded workforce is
difficult.

2) The operating system and most programming libraries still use error
codes. So, wherever you interface to the OS you are forced to use
error codes. That probably won't change because those operating system
functions (APIs) need to be generic enough for many different
languages to use. And I don't see how they are going to completely
rewrite the operating system to use exceptions.

3) No consistent exception policy. The entire project should have at
least a good base class Exception object, and not the one provided by
the libraries. Use your own.

>
> I've finally come around to Dave Abrahams' view:
>
> Exceptions are basically just glorified return codes

> with different semantics,
>

Have him come on here and discuss it with us.

> the main semantic differences being that exceptions: a) can't be ignored; b)
> don't have to be manually propagated up to a suitable handler; and c)
> require some more care in intermediate code so that stack unwinding is safe.
> The first two are clear advantages; the last is now (finally)
> well-understood but does require extra coding discipline and will continue
> to be a source of articles and talks and maybe even some new analysis about
> cases not yet discovered/covered (although it's widely believed that the
> area is indeed now sufficiently well covered to declare it "well-understood"
> as I just did).

You left out a big one: Exceptions can return any type of object, and all the
error-information you need.

>
> Let me float an idea and see what comes out: A lot of people lump the choice
> of exceptions vs. return codes into the error handling strategy, but I think
> it's useful to distinguish between the mechanism and the strategy. That is,
> choices about error handling strategy (what errors to detect/report, and
> what/where to correct them) could be orthogonal to the reporting method (the
> middle piece, what mechanism to use to report them); together, both would
> form the error handling policy. Comments? Reactions?
>

I'm not sure what you mean. But I think you are promoting
exceptions. You see, exceptions promote orthogonality. Throwers of a
proper Exception class (based in a common base class) don't have to be
concerned about side effects as far as compiling and linking
go. Returners of error codes need to know what the calling function is
expecting as a return value. Not very orthogonal.

Of course, I could be completely wrong about all of the above. :)

I have to get back to work now.

Walt Howard

Andy Watson

unread,
Dec 14, 2000, 11:41:42 AM12/14/00
to
On 13 Dec 2000 16:09:13 -0500, Herb Sutter <hsu...@peerdirect.com>
wrote:

>James Kanze <James...@dresdner-bank.com> writes:
>>exceptions should only be used for exceptional cases
>
>This is a commonly-repeated (I used to say it too) but fuzzy statement. Its
>main problem, borne out in many newsgroup discussions, is that what's "truly
>exceptional" is subjective and hasn't so far been a reliable guide. Some
>think it means hard errors where the system is going to crash anyway. Others
>think it also includes serious errors where a major operation can't be
>completed. Still others think it means when any operation, large or small,
>can't be completed.

>A few people would even include "success with info"
>warnings, meaning anything beyond "OK, done" would be an exception -- to
>them, anything short of clear success is to them an "exceptional case."

I guess this approach would be true if one was coding from the Use
Case. In there it is common for a normal flow to be documented and
exceptions to the rule to also be documented. If one was developing
using this idiom then I guess exceptions would fit.

Andy

Ivan Vecerina

unread,
Dec 14, 2000, 12:07:59 PM12/14/00
to
Gabriel Zachmann said:
>I am trying to decide whether or not to use exceptions.

>But I'm afraid I still don't see if there is a consensus
>whether or not
> Exceptions are a Good Thing?

By now, you've probably found out that it is a matter of choosing
a programming style. But the C++ libraries are geared towards
leveraging exceptions, and the RAII idiom (resource acquisition
is initialization). When considering the use of exceptions in C++,
make sure you understand RAII first: it is essential for exceptions
to be usable, and invites you to use exceptions in constructors.

Being able to create the objects=resources that you will use
is a first step towards being able to accomplis a task.
Then you call functions to perform operations using the resources.
If it is normally expected that the operations will succeed, you
do not need to bother handling error codes.
If an unexpected error occurs at any point, only some top-level
handler needs to bother handling it (e.g. display a diagnostic
message to the user).

>I found a lot of tips and discussion about the technicalities of
>exceptions, but the big question is


> From what I read, there seems to be a consensus that:
>1. Writing exception-safe code is harder than without exceptions;

There are mostly style issues that one has to be careful with.

>2. Excpetions introduce a second path of control flow "behind the scenes",

> which increases the complexity of the code;

Not true in my perspective: using exceptions keeps you from having
to bother with error handling in many situations: no need to test
for error codes, no need to check if malloc returned zero, etc...
Error handling is only needed in the parts of the code where
errors are actually corrected.

However, this comes at the cost of having to obey some style rules.
The logic is different from most procedural languages, and often
seen as complicated.

>3. In order to do decent error-handling in constructors, you must use
> exceptions.

Yes. RAII and exceptions work hand in hand.

>So, my questions are:
>a) should I use exceptions only for constructors and error codes for
> all other methods?

No, be consistent. I would recommend using exceptions.
Many useful C++ library functions and objects (e.g. containers) will
throw exceptions anyway.

Note that some prefer taking the opposite approach (have 'do nothing'
constructors, and then a separate initialization function which
returns an error code) - which you'll find in some popular libraries
(such as MFC). I find that those are a pain to use ...

>b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> method?)

Again, it is important to remain consistent.

>c) should exceptions be used only for "exceptional" cases, or could they
> also be used for not-so-exceptional things, like bogus parameters passed
> in from the caller?

As others, I would think that bogus parameters is usually a programming
error, and is therefore intended to be exceptional.

But if a failure is expected to be common, do not hesitate to return
a status code. Also remember that you can provide two versions of the
same function: one that throws an exception for users that do not want
to bother with error handling (or expect that no error shall occur),
and one that returns a success code (e.g. a bool) for users that expect
that the operation is likely to fail.

A good criterion is that you should only have few try{}catch(...)
blocks in your application. If there are many, then maybe:
- you should create RAII classes, or use existing ones (auto_ptr and
all the containers for example).
- you are using exceptions when a return code would be better.

I hope that this perspective will help,
Ivan

--
Ivan Vecerina - Surgical Navigation Network
--
Brainbench MVP for C++
http://www.brainbench.com

Harri

unread,
Dec 14, 2000, 2:16:12 PM12/14/00
to
> > Easy.
> >
> > Have the constructor do nothing.
> >
> > Constructor()
> > {
> > }
> >
> > Then have an Init() function that does the actual initialization.
>
> But this idiom introduces a completely new kind of error -- attempts to
access an
> uninitialized object.
> Does every member function test to make sure the object has been
initialized?
> That's a lot of clutter in the code. Or do you just allow the use of
> uninitialized objects to eventually cause a crash?

In EPOC you are forced to use two-phase construction all the time, because
their wonky setjmp/longjmp "exception" mechanism doesn't call destructors
when you throw. The way they get round it is simply to make a factory
function for everything, like this

class CThing : public CBase{
public:
static CThing* NewLC(){
CThing* self = new CThing();
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
private:
CThing(); // can't throw
ConstructL(); // does the things that throw
};

(Anything on the CleanupStack gets deleted if you throw, and inheriting from
CBase zeros the memory, so deleting what is in effect a half constructed
object is more likely to work)

You could change this to use return values I suppose.

Note that using this idiom means that any class with initialisation stuff
that might go wrong cannot be instantiated on the stack. This breaks most
RIIA stuff you might want to do. It makes your code slower. It means you
have to type in all that stuff repeatedly. It may also give you boils.

Ken Hagan

unread,
Dec 14, 2000, 4:36:10 PM12/14/00
to
"Herb Sutter" <hsu...@peerdirect.com> wrote...

>
> I've finally come around to Dave Abrahams' view:
>
> Exceptions are basically just glorified return codes
> with different semantics,
>
> the main semantic differences being that exceptions:
> a) can't be ignored;
> b) don't have to be manually propagated up to a suitable handler;
> c) require some more care in intermediate code so that stack
> unwinding is safe.

You missed out
d) are more expensive when the exception is "often" thrown.

but I agree that a+b are a Good Thing. Your c is a discipline that
most of us are still absorbing into our sub-consciousness, but at
least the ground rules are now known.

> ... choices about error handling strategy (what errors to detect/report,


> and what/where to correct them) could be orthogonal to the reporting
> method (the middle piece, what mechanism to use to report them);
> together, both would form the error handling policy. Comments? Reactions?

I'm not sure what you mean by error handling policy. Can you define
it without reference to the two orthogonal considerations you've just
mentioned?

I agree that return codes and exceptions are just mechanisms, and I
can think of three reasons to choose one or other.

1) Performance: The "error" is sufficiently common that exceptions
are too expensive, or sufficiently uncommon that checking return
codes is too expensive. Of course, our estimate of how often
it will fail depends on our assumptions about use. The classic
example is opening files. Failing to open our own executable image
is surely unexpected, but failure to open a file when our user
had to type in a long path name by hand is surely the expected case.

2) Verbosity: "try {stuff();} catch (xyz) {fix();}" is more typing
than "if (!stuff()) fix()" for certain values of stuff and fix.
If the "error" is unlikely to be handled or even inspected by its
immediate caller, then your point b favours the use of exceptions.
RAII can be used to reduce this likelihood by automating the
rollback that intervening layers need to perform, but I don't
think this is possible in every case, and it is itself a source
of verbosity, so it merely alters the arithmetic. It doesn't
provide a killer argument in favour of exceptions in every case.

3) The environment demands one or the other. Some functions in C++
have to use exceptions to indicate an error, and some functions
have to use return codes because of compatibililty with non-C++
code. This is obviously a killer argument for these functions, but
can also influence the previous two reasons in the case of functions
that are likely to be called indirectly from such an environment.
Some embedded programmers (no, I don't mean that literally) might
use this to justify a blanket ban on exceptions and using functions
that throw them.

Indeed, I would advance these as the only rational basis for making the
choice, in a sort of "please don't toast me I was only thinking aloud"
kind of way.

James Kanze

unread,
Dec 14, 2000, 4:38:23 PM12/14/00
to
Mark Wilden wrote:

> "James Kanze" <James...@dresdner-bank.com> wrote in message
> news:3A376900...@dresdner-bank.com...

> > [An Init method] It means that you don't have to deal with
> > exceptions coming from that constructor. If you defer anything
> > that can fail to a later initialize function, you can handle a
> > return code.

> But I wouldn't regard this as an advantage, as I believe failures
> should be handled via the exception mechanism.

Consider my answer in context. At one point, it was suggested that
you should only use exceptions from the constructor; in other cases,
use return codes. All I'm pointing out here is that if exceptions are
"bad" (for whatever reason), then they are equally bad from
constructors, and that there are ways to handle errors.

If you are using exceptions, of course, there is no reason not to use
them in the constructor. Supposing a modern compiler; I know of some
compilers, in the past, that wouldn't free the memory if the
constructor in a new expression failed because of an exception.

> > If you use a factory, you can delete the object if the
> > initialization fails, and return a null pointer.

> If the failure comes from the constructor, there is no need to
> delete the object, of course.

If the failure is signaled by an exception, and the compiler is
standards conforming in this regard. I've used compilers without
exceptions, and worse, I've used compilers with exceptions, but which
didn't delete the memory correctly. (I don't think that this is a
problem with any current releases, but be warned if you have to use an
older compiler.)

> > If on the other hand, you use an internal
> > failure flag, like iostream, you can integrate the error handling into
> > that of the normal case, again like iostream.

> True...that's never especially appealed to me, though.

Actually, in the ofstream case, at least, I find it very nice, most of
the time. I can just ignore the error, and check it once at the end,
when I close the file. (Note that the error will typically not occur
immediately when I write the character, but only when the ofstream
flushes to disk. So it is deferred anyway.)

On the other hand, that doesn't cover errors for things like open.
There, I will check the results immediately, since "cannot open xxx"
is a distinctly different type of error than "write error on xxx".

> > Globally, making it an absolute rule not to throw from a
> > constructor only makes sense (to me) if you are designing to not
> > use exceptions anywhere.

> Agreed.

> > But even in constructors, exceptions should only be used for
> > exceptional cases, so you will occasionally have cases where other
> > mechanisms are needed anyway.

> Guess I'd have to see a specific case.

Just about every case is specific, in some way. I don't like using
exceptions for errors on user input, for example. In a real sense,
these aren't "errors"; your reaction should be part of your standard
behavior.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Walt Howard

unread,
Dec 14, 2000, 9:51:00 PM12/14/00
to
For me, this argument is almost irrelevant. I can't remember the last
time I ran out of memory since I work on virtual memory systems. But
the proper way to solve this is to overload new and delete with your
own versions. At program start, have your program new() up some
reserve memory. When new fails, have it popup a message to the user
that he is running out of memory, and to do something
appropriate. Then, release the reserve memory and continue the
program. European cars and aircraft have been doing this with fuel
almost since they were invented. It's so simple I could write it here
off the cuff:

void* operator new( size_t bytes )
{
static void* reserve = malloc( 40000 );
void* p = malloc( bytes);
if ( !p )
{
MessageBox( NULL, "You are running out of memory", "WARNING", NULL );
free(reserve);
p = malloc(bytes);

}
return p;
}

void operator delete( void* ptr )
{
free( ptr );
}

Walt Howard

Albrecht Fritzsche <albrecht....@alfabet.de> writes:

> Mark Wilden wrote:
> >
> > However, how does one manage this with constructors in particular?
> > How does one design a constructor so that it doesn't care if the
> > machine is out of memory, or if a needed file doesn't exist?
>
> What about a constructor like
>
> struct X{
> X() { try { Init(); /* ... */ } catch(...){} }
> void Init() { /* ... */}
> };
>
> I am starting to respect exception safety more and more and am
> reasoning about those problems either.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Dec 15, 2000, 12:01:35 AM12/15/00
to
Herb Sutter wrote:

> James Kanze <James...@dresdner-bank.com> writes:
> >exceptions should only be used for exceptional cases

> This is a commonly-repeated (I used to say it too) but fuzzy
> statement. Its main problem, borne out in many newsgroup
> discussions, is that what's "truly exceptional" is subjective and
> hasn't so far been a reliable guide. Some think it means hard errors
> where the system is going to crash anyway. Others think it also
> includes serious errors where a major operation can't be
> completed. Still others think it means when any operation, large or
> small, can't be completed. A few people would even include "success
> with info" warnings, meaning anything beyond "OK, done" would be an
> exception -- to them, anything short of clear success is to them an
> "exceptional case."

Agreed. For some software, the "exceptional" case would be that it
actually worked:-).

> So my question is: What does "exceptional cases" mean to you? Can
> you give a clear and rigorous definition that can be used to make
> decisions about new cases? If so, I can take the definition and
> apply it to some cases and see whether or not I agree with it --
> and, more importantly, why or why not. Again, in fairness, I used
> to say the same thing, and after a several muddled attempts over
> time I realized I was guilty of fuzzy thinking because I couldn't
> decide on a clear and unambiguous definition.

I cannot really give a precise definition either. I just said it
because everybody says it. My own criteria are somewhat different,
but perhaps too restrictive for most people: use exceptions when the
only reasonable action is to abort, otherwise, return codes. And when
in doubt, use a return code; the user can always wrap it to throw an
exception, with little additional overhead. (The reverse is much more
expensive.)

> I've finally come around to Dave Abrahams' view:

> Exceptions are basically just glorified return codes
> with different semantics,

Which, of course, depends on what you mean by return codes. There's
certainly a difference between exceptions and the return value of
sin(double) (and I don't think that even Dave would recommend that sin
use an exception to return its result). If by return codes, you mean
only error reporting mechanisms, then yes. Exceptions are an error
reporting mechanism.

> the main semantic differences being that exceptions: a) can't be
> ignored;

But that's true of my ReturnCode class.

> b) don't have to be manually propagated up to a suitable
> handler; and c) require some more care in intermediate code so that
> stack unwinding is safe.

The advantage and the disadvantage.

> The first two are clear advantages; the
> last is now (finally) well-understood

By you, Dave, and perhaps a few readers of this newsgroup. From what
I've seen, I'd guess that this is only true for about 1% or 2% of the
programmers, however.

> but does require extra coding
> discipline and will continue to be a source of articles and talks
> and maybe even some new analysis about cases not yet
> discovered/covered (although it's widely believed that the area is
> indeed now sufficiently well covered to declare it "well-understood"
> as I just did).

There are two aspects to "well understood". The problem is certainly
well understood. Some solutions are known, but I wouldn't say that
globally, the solutions are well understood. And again, I'm only
talking about people who regularly read this newsgroup -- globally, my
impression is that most programmers aren't even aware that there is a
problem to understand.

> Let me float an idea and see what comes out: A lot of people lump
> the choice of exceptions vs. return codes into the error handling
> strategy, but I think it's useful to distinguish between the
> mechanism and the strategy. That is, choices about error handling
> strategy (what errors to detect/report, and what/where to correct
> them) could be orthogonal to the reporting method (the middle piece,
> what mechanism to use to report them); together, both would form the
> error handling policy. Comments? Reactions?

I've often posted that exceptions are only a implementation mechanism
for transmitting errors; their use (or not) doesn't affect the design
of error handling in general. IMHO, there are three aspects to error
handling in general: detection, reporting and handling. Exceptions
are irrelevant for the first and the last, and in many ways, just an
implementation detail with regards to the second: they concern the
how, but not the what.

In this regard, I find that most people ask the question, exceptions
or not, way to soon. How can you decide on the merits of an
implementation detail if you don't know what you want to implement?

The other point I've noticed, and this still seems to be true, despite
Dave's constant lecturing to the contrary, is that most people tend to
think of exception safety, when they think of it at all, in terms of
memory leaks, or at the most, resource management, and not in terms of
total program coherence. If resource management were the only
concern, exception safety would be trivial.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Walt Howard

unread,
Dec 15, 2000, 10:37:32 AM12/15/00
to
Kevin Cline <kcl...@mayannetworks.com> writes:

> Walt Howard wrote:
>
> > Easy.
> >
> > Have the constructor do nothing.
> >
> > Constructor()
> > {
> > }
> >
> > Then have an Init() function that does the actual initialization.
> >
> > You asked.
> >
> > It buys a big plus in some situations, delayed activation...
>
> But this idiom introduces a completely new kind of error -- attempts to
access an
> uninitialized object.
> Does every member function test to make sure the object has been
initialized?
> That's a lot of clutter in the code. Or do you just allow the use of
> uninitialized objects to eventually cause a crash?

Yes. Every member function can do it.

if ( !Initialized )
Initialize();

Woop dee doo.

I'm afraid there are situations where you have no choice but to delay
activation. The object is still constructed properly. It won't cause a
crash to use it. It's just not fully operational yet. Like a socket
object that isn't connected yet. Trying to write to it will just get
you an error or exception, not a crash.

Walt Howard

Francis Glassborow

unread,
Dec 15, 2000, 10:43:10 AM12/15/00
to
In article <wkn1dzm...@wallyware.com>, Walt Howard
<wa...@wallyware.com> writes

>You left out a big one: Exceptions can return any type of object, and all the
>error-information you need.

So can return values.

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Kevin Cline

unread,
Dec 15, 2000, 10:44:48 AM12/15/00
to
Mark Wilden wrote:

> "Kevin Cline" <kcl...@mayannetworks.com> wrote in message
> news:3A37BF13...@mayannetworks.com...
>
> > Does every member function test to make sure the object has been
> initialized?
> > That's a lot of clutter in the code.
>
> It's not so bad. In my COM work (where two-stage init is required, at least as
> far as I can see), I just have a macro (!) that checks the state and throws an
> exception, if nec.--one line of code.

Why would you use a macro instead of an inline function call?

class X {
private:
inline init_test() { if (!initialized) throw unitialized; }

Herb Sutter

unread,
Dec 15, 2000, 11:00:11 AM12/15/00
to
Matthew Collett <m.co...@auckland.ac.nz> writes:

>Herb Sutter <hsu...@peerdirect.com> wrote:
>
>>James Kanze <James...@dresdner-bank.com> writes:
>>>exceptions should only be used for exceptional cases
>>
>>This is a commonly-repeated (I used to say it too) but fuzzy statement.
>>
>>So my question is: What does "exceptional cases" mean to you?
>

>In principle: an exception occurs when a function cannot satisfy its
>stated or implied post-conditions even though the caller met its
>pre-conditions.

OK, I'll bite: Does that include warnings and success-with-info? Also, how
should other problems (such as parameter and precondition errors) be
reported?

>In practice, this is to some extent circular, since the definition of
>the post-conditions will depend on how errors are going to be reported.

Herb

---
Herb Sutter (mailto:hsu...@peerdirect.com)

CTO, PeerDirect Inc. (http://www.peerdirect.com)
Contributing Editor, C/C++ Users Journal (http://www.cuj.com)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Dec 15, 2000, 2:58:07 PM12/15/00
to
Walt Howard wrote:

[...]
> Why errorcodes suck.
[...]


> 2) You can only return a small amount of information, usually a
> number.

How does "throw ErrorState" return more information than "return
ErrorState"?

> This is often insufficient to correct the error. For example, your
> fileopen function fails and returns an error 5, Access
> denied. Great, no problema. Wouldn't it be nice to know which
> filename failed? You say, "That's stupid! The calling function knows
> which filename it used!". Are you sure? Maybe that's why the
> fileopen failed, you weren't using the right filename to begin
> with. In fact I'd be willing to be that 99% of failed opens are
> caused by wrong filename.

The question of what to report is orthogonal to the question of how to
report it. The difference between return codes and exceptions only
addresses how errors are reported, not what information the report
contains.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Wil Evers

unread,
Dec 15, 2000, 3:06:52 PM12/15/00
to
In article <t3fb375...@news.supernews.com>, Mark Wilden wrote:

> "Wil Evers" <bou...@dev.null> wrote in message
> news:jhi519...@tinus.intra.doosys.com...

> > Rather then letting the program muddle on, I believe it is usually


> > better to have it log as much error information as possible and
> > then abort, leaving it up to whatever/whoever invoked it to
> > take appropriate action.
>
> Repeat after me: It all depends on the program.

It all depends on the program :-).



> Every program will have different costs and benefits of "muddling
> on". If the cost is low enough (the program can't do much
> harm--it's not guiding missiles or anything) and/or the benefit is
> high enough (by not aborting, you at least give the user the chance
> to save her work), then muddling on is appropriate.

OK, I'll bite.

What we have is a program that just decided it can no longer trust
itself. We also have a user who just spent hours typing that crucial
document for that important business meeting tomorrow. Now what
should the program do?

Obviously, the bug should be fixed, but that is no help to our poor
user. At the very least, the program should try to report what went
wrong. And yes, it could try to save the user's work, provided the
saved copy is clearly marked as untrusted.

But should it ever try to return to its main loop, knowing that its
internal state is inconsistent, risking the chance of making things
worse for the user? Unless there is really nothing to fall back on
(like a user shell, a desktop OS, or a watchdog timer), my answer is
no. An unambiguous refusal to continue will at least stop the
marketing people from claiming there is no problem.

As a library writer, this is an important issue to me. By saying
that it all depends on the program, you're suggesting that throwing
an exception may be appropriate for reporting a programming error. I
only throw exceptions for unexpected conditions like running out of
resources. When I detect a programming error, my strategy is to call
some user-supplied routine, after which I force a core dump.

- Wil

--
Wil Evers, DOOSYS IT Consultants, Maarssen, Holland
[Wil underscore Evers at doosys dot com]

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Dec 15, 2000, 3:51:25 PM12/15/00
to
Francis Glassborow wrote:

[...]


> 1) Set a global variable and trust that it will be checked. I recently
> asked a dozen attendees at on an Advanced C++ Development techniques
> course to raise their hands if they had ever checked errno. I was
> surprised that two actually claimed to have done so.

Surprised that the number was so high, or that it was so low. I've
never actually had a need to check errno. Errno doesn't tell you
whether an error has occured or not; it only defines what the error
was IF one occured. So the only time you would check errno is if you
wanted additional information concerning the type of error.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Daniel James

unread,
Dec 15, 2000, 7:01:14 PM12/15/00
to
In article <slrn93a6ke...@schwind.igd.fhg.de>, Gabriel Zachmann wrote:
> 1. Writing exception-safe code is harder than without exceptions;

Exception-safety is another thing to think about, another issue to build into
your design. It does make it harder to produce a good design, yes, but the
difference is not great once you become accustomed to thinking about
exceptions.

Whether or not you throw exceptions from your own code you have to be aware
that exceptions are the standard way that much of the C++ runtime library
reports failure. You have to make your code exception-safe or be sure that
you don't use those parts of the library (or anything else that can throw).

I think, really, you *have* to write exception-safe code whether you want to
use exceptions yourself or not, so this shouldn't really affect your
decision.

> 2. Excpetions introduce a second path of control flow "behind the scenes",
> which increases the complexity of the code;

If a function can throw it will have multiple exit paths. I've always
followed a coding standard that prohibits multiple returns from a function
and exceptions essentially violate that standard. I do find that this makes
the code a little harder to follow, but it is no worse than allowing multiple
returns.

> 3. In order to do decent error-handling in constructors, you must use
> exceptions.

Well, it's true that a constructor can't return an error code, and that
throwing an exception is quite a nice way to report constructor failure. It's
not the only way, as other posters have pointed out, but I think it results
in much cleaner code than using tricks like an error flag in an object that
is set if the constructor fails.

> So, my questions are:
> a) should I use exceptions only for constructors and error codes for
> all other methods?

No, I'd say that if you are going to use exceptions at all you should use
them everywhere. Once you bite the bullet and make your code exception safe
and include code to catch some errors as exceptions there's very little
reason to avoid the technique in other cases.

> b) if exceptions are used in general, should functions return *only*
> error codes *or* throw exceptions? (i.e., is it ok to mix both in one
> method?)

It may be appropriate for some functions to return an error code for errors
that can be handled by their immediate caller but to throw an exception to
report errors that are too severe to correct and retry, but I would advise
you to use this technique sparingly and document it well because I have found
that that *can* make code confusing and hard to follow. (...or is it just
that I'm not yet used to reading code that does that?)

> c) should exceptions be used only for "exceptional" cases, or could they
> also be used for not-so-exceptional things, like bogus parameters passed
> in from the caller?

I don't think any two authorities will agree completely on what makes a case
"exceptional". I'd say that exceptions should only be used for runtime errors
- if by "bogus parameters" you mean something that is a coding error you
should probably detect them some other way, maybe an assertion. I see nothing
wrong with using an exception to report a bad parameter that is caused by bad
user input, badly formatted data, whatever.

> All insights and pointers will be greatly appreciated.

I've recently had occasion to rewrite some parts of a small application using
exceptions where I had previously used error codes. The application in
question uses two 3rd-party libraries which both use exceptions to report
errors. In my first version I had to wrap each call that could throw in a
try/catch block and convert any exception into an error code. I decided that
that was silly and - when I was asked to make some enhancements that were
going to add greatly to the number of calls that would have to be wrapped -
converted the whole application to use exceptions throughout.

The result was a much cleaner-looking (i.e. easier to read and to maintain)
body of code, I was able to remove almost all the try/catch blocks and all
the error-code handling code. This has been a great advantage.

There have been some sticking points, though:

- Neither of the 3rd-party libraries uses exceptions based on the standard
exception type so when I have to catch an exception I have to remember to
catch all the types of exception that can be thrown - I can't just catch by a
single base class. Of course, exception safety is about a lot more than
try/catch blocks - I recommend the section on exception safety in Herb
Sutter's "Exceptional C++" which explains the issues at least as well as
anything else I've seen.

- The two libraries contain conflicting definitions of a number of macros,
and their header files cannot both be included in the same source file (one
does not use namespaces and the other places 'using' directives in many of
its headers) so I've had to wrap one of the libraries in a "pImpl" class that
catches any exception thrown by the library and re-throws an exception type
defined by my application.

- both of the libraries throw exception objects that contain a text string
describing the condition that cause the exception to be thrown. These strings
are in English, but my application has to support more than one language.

I think that the moral of the story here is that exceptions thrown from
third-party libraries can be a problem if those libraries implement their own
exception objects not derived from the standard exception classes. If
libraries used a standard class such as domain_error (or a class derived
from, e.g. domain_error) it would be much easier for an application to manage
exceptions in a uniform manner - but the fact that domain_error uses a text
string to provide information about the error causes difficulties with
internationalization. My application's own exception objects hold message
numbers that are used to look up messages in a locale-dependent table for
display - it's a pity std::domain_error doesn't work this way.

One difficulty that has arisen from the use of exceptions as a general
error-reporting mechanism in the application is that exceptions may be thrown
from very low-level routines and caught at the top-level of the user
interface. When an exception is caught the handler knows nothing of the
context within which the exception was thrown. Everything has been unwound
neatly from the point of failure and the application is stable, but the
information available for display to the user often contains too little
contextual information to allow the user to work out what actually went
wrong. I'm trying to invent a mechanism for adding context information to
what is held in the exception object, so that a more meaningful message can
be displayed to the user - without catching the exception an rethrowing it at
every level! I'd be interested to hear whether anyone else has tackled this
problem before.

Cheers,
Daniel
[nospam.demon.co.uk is a spam-magnet. Replace nospam with sonadata to reply]

Daniel James

unread,
Dec 15, 2000, 7:01:32 PM12/15/00
to
In article <91a2ga$kpv$1...@reader0.news.uk.quza.net>, Harri wrote:
> In EPOC you are forced to use two-phase construction all the time, because
> their wonky setjmp/longjmp "exception" mechanism doesn't call destructors
> when you throw.
>

It's probably worth interjecting here - for those who don't know - that EPOC
is the OS supplied by Symbian for use in handheld computers, smartphones and
things of that ilk. EPOC code is written using an early version of the GNU
toolchain for the ARM processor that didn't have support for exceptions and
so the whole API is written to use an error-handling mechanism based around
functions that can "Leave" - a condition that must be handled using a
"Trap".

The Leave/Trap mechanisms is now so deeply enmeshed with the EPOC API that
it seems doubtful that it will ever be replaced with standard exceptions,
even though newer versions of the GNU tools are now available.

All of this is a kludge to facilitate structured handling of errors within
EPOC using a C++ subset that doesn't support exceptions - it is a good
kludge, in that it works well given the constraints of the environment - but
it is not strictly germane to the discussion of error handling in an
ISO-compliant C++ system.

Harri's observations:

> Note that using this idiom means that any class with initialisation stuff
> that might go wrong cannot be instantiated on the stack. This breaks most
> RIIA stuff you might want to do. It makes your code slower. It means you
> have to type in all that stuff repeatedly. It may also give you boils.

are certainly valid - I'd much rather use real C++ exceptions than the
Leave/Trap mechanism, though the latter has never yet given me boils!

Cheers,
Daniel
[nospam.demon.co.uk is a spam-magnet. Replace nospam with sonadata to reply]

Gerhard Menzl

unread,
Dec 16, 2000, 3:25:48 AM12/16/00
to
Walt Howard wrote:

> For me, this argument is almost irrelevant. I can't remember the last
> time I ran out of memory since I work on virtual memory systems. But
> the proper way to solve this is to overload new and delete with your
> own versions. At program start, have your program new() up some
> reserve memory. When new fails, have it popup a message to the user
> that he is running out of memory, and to do something
> appropriate. Then, release the reserve memory and continue the
> program. European cars and aircraft have been doing this with fuel
> almost since they were invented. It's so simple I could write it here
> off the cuff:

Is it really that simple?

> void* operator new( size_t bytes )
> {
> static void* reserve = malloc( 40000 );
> void* p = malloc( bytes);
> if ( !p )
> {
> MessageBox( NULL, "You are running out of memory",
> "WARNING", NULL );
> free(reserve);
> p = malloc(bytes);
>
> }
> return p;
> }
>
> void operator delete( void* ptr )
> {
> free( ptr );
> }

Sadly, this will fail with:

struct Big
{
char buffer[50000];
};

void f ()
{
Big* p = new Big;
//...
}

The point, of course, is: how much reserve memory is enough? Just as
that spare gallon or 4 litres of fuel may be useless if you happen to
tap it in central Nevada or north Sweden, an arbitrary amount of extra
memory cannot guarantee that allocation will always succeed. Apart from
that:

- What is the appropriate thing to do for a user, and how is a user to
know?

- There are millions of systems that run without user interaction and
don't even have a screen to pop a message box on.

For these reasons, the argument is certainly not irrelevant, I think.

Gerhard Menzl

Mark Wilden

unread,
Dec 16, 2000, 4:17:09 AM12/16/00
to
"Kevin Cline" <kcl...@mayannetworks.com> wrote in message
news:3A39044A...@mayannetworks.com...

> Mark Wilden wrote:
>
> > It's not so bad. In my COM work (where two-stage init is required, at least
as
> > far as I can see), I just have a macro (!) that checks the state and throws
an
> > exception, if nec.--one line of code.
>
> Why would you use a macro instead of an inline function call?
>
> class X {
> private:
> inline init_test() { if (!initialized) throw unitialized; }
> }

Because I need to stick __FILE__ and __LINE__ in there. Also, a companion
macro doesn't throw, it returns from the current function.

Jeff Connelly

unread,
Dec 16, 2000, 4:35:14 AM12/16/00
to
In article <3A39E09C...@dresdner-bank.com>,

James Kanze <James...@dresdner-bank.com> wrote:
> Walt Howard wrote:
>
> [...]
> > Why errorcodes suck.
> [...]
> > 2) You can only return a small amount of information, usually a
> > number.
>
> How does "throw ErrorState" return more information than "return
> ErrorState"?
>
> > This is often insufficient to correct the error. For example, your
> > fileopen function fails and returns an error 5, Access
> > denied. Great, no problema. Wouldn't it be nice to know which
> > filename failed? You say, "That's stupid! The calling function knows
> > which filename it used!". Are you sure? Maybe that's why the
> > fileopen failed, you weren't using the right filename to begin
> > with. In fact I'd be willing to be that 99% of failed opens are
> > caused by wrong filename.
>
> The question of what to report is orthogonal to the question of how to
> report it. The difference between return codes and exceptions only
> addresses how errors are reported, not what information the report
> contains.

What you don't seem to be realizing is that exceptions are objects that
can contain virtually all the information you want them to contain.
Not only that but they can be handled all in one place where you can
have fairly lengthy or sophisticated error checking that would be very
awkward to place everywhere there is a function call on up the chain.

--
Regards,
Jeff


Sent via Deja.com
http://www.deja.com/

Mark Wilden

unread,
Dec 16, 2000, 4:40:05 AM12/16/00
to
"Wil Evers" <bou...@dev.null> wrote in message
news:24pc19...@tinus.intra.doosys.com...

>
> What we have is a program that just decided it can no longer trust
> itself. We also have a user who just spent hours typing that crucial
> document for that important business meeting tomorrow. Now what
> should the program do?

I think you answered your own question...

> Obviously, the bug should be fixed, but that is no help to our poor
> user. At the very least, the program should try to report what went
> wrong. And yes, it could try to save the user's work, provided the
> saved copy is clearly marked as untrusted.

> But should it ever try to return to its main loop, knowing that its
> internal state is inconsistent

It depends. :) I don't think one can make a single general rule for this
stuff.

> By saying
> that it all depends on the program, you're suggesting that throwing
> an exception may be appropriate for reporting a programming error.

Absolutely. For one thing, it's not always clear whether an error is a
"programming error" or not, which is why I tend not to distinguish
between them.
For example, in the app I'm working on, a customer wants to download a
file. The
database says the file's website's customer is unknown. Is that a programming
error, or a config error or a database load error or what? Is it
"exceptional"?
The answer is, I don't care. :) I'll let the user download the file. The
system
returns to its main loop and carries on.

> I only throw exceptions for unexpected conditions like running out of
> resources. When I detect a programming error, my strategy is to call
> some user-supplied routine, after which I force a core dump.

It seems to me that you're dictating how programming errors are handled
in your
library, and that's fine, of course. I prefer to let the client decide how to
handle errors (of all kinds), and that's what exceptions are for.

Herb Sutter

unread,
Dec 16, 2000, 4:45:39 AM12/16/00