Arguments *Against* Exception Use

  • Thread starter Scott Brady Drummonds
  • Start date
S

Scott Brady Drummonds

Hi, all,

I just got out of a meeting with a team of software developers that I
recently joined as they are staffing to create a medium-sized project
(potentially all of which will be written in C++). From my experience and
readings, I've come to this group indoctrinated to use exceptions for error
handling. The experience in this group that leads them to believe that
exceptions should only be used where severe runtime errors require program
termination is mainly based on the notion that the performance impact of
exceptions is prohibitive.

Besides the Meyers books and my trusty copy of "C++ FAQs", I'm going on my
intuition based on years of experience. Am I over-indoctrinated in the use
of exceptions? Are there some warnings that I'm not heeding? Can
exceptions impact performance to the degree that my coworkers claim? I'd
like to hear some anti-exception thoughts, if they exist.

Thanks!
Scott
 
A

Alf P. Steinbach

* Scott Brady Drummonds:
Hi, all,

I just got out of a meeting with a team of software developers that I
recently joined as they are staffing to create a medium-sized project
(potentially all of which will be written in C++). From my experience and
readings, I've come to this group indoctrinated to use exceptions for error
handling. The experience in this group that leads them to believe that
exceptions should only be used where severe runtime errors require program
termination is mainly based on the notion that the performance impact of
exceptions is prohibitive.

Besides the Meyers books and my trusty copy of "C++ FAQs", I'm going on my
intuition based on years of experience. Am I over-indoctrinated in the use
of exceptions? Are there some warnings that I'm not heeding? Can
exceptions impact performance to the degree that my coworkers claim? I'd
like to hear some anti-exception thoughts, if they exist.

Context?

If coding for a micro-controller or, say, an OS kernel: yes, C++ exceptions
are probably UnGood.

Otherwise: no, C++ exceptions are Good.

But regardless of context, if the question is really on the table, then one
reasonable way to proceed could be to measure typical code. Things to
measure: time needed to complete correctly functioning code, time needed to do
some modification of the code, execution time in ordinary usage.

I bet those software developers think raw pointers and Hungarian notation (not
to mention a "repository" to copy code snippets from!) are nice ideas, too...
 
G

Guest

I'd like to hear some anti-exception thoughts, if they exist.

You may want to read Herb Sutter's article named When and How to Use
Exceptions, in the August 2004 issue of the C/C++ Users Journal.

If you decide to use exceptions in the project, the section dedicated to
exceptions in the book Exceptional C++ by Herb Sutter will be
exceptionally useful :) There are sequels to this book, which should be
helpful too, but I haven't read them yet:

http://www.gotw.ca/publications/index.htm

Ali
 
C

Cy Edmunds

Scott Brady Drummonds said:
Hi, all,

I just got out of a meeting with a team of software developers that I
recently joined as they are staffing to create a medium-sized project
(potentially all of which will be written in C++). From my experience and
readings, I've come to this group indoctrinated to use exceptions for
error
handling. The experience in this group that leads them to believe that
exceptions should only be used where severe runtime errors require program
termination is mainly based on the notion that the performance impact of
exceptions is prohibitive.

Besides the Meyers books and my trusty copy of "C++ FAQs", I'm going on my
intuition based on years of experience. Am I over-indoctrinated in the
use
of exceptions? Are there some warnings that I'm not heeding? Can
exceptions impact performance to the degree that my coworkers claim? I'd
like to hear some anti-exception thoughts, if they exist.

Thanks!
Scott

I never could figure out how use of exceptions could cause such big run time
errors. If you use them properly as error handlers rather than control
structures they won't be invoked often enough to run up much execution time.
And if you avoid exception specifications (which are basically useless
anyway) they don't have much overhead at all.
 
E

E. Robert Tisdale

Scott said:
I just got out of a meeting with a team of software developers
that I recently joined as they are staffing to create
a medium-sized project (potentially all of which will be written in C++).
From my experience and readings,
I've come to this group indoctrinated to use exceptions for error handling.
The experience in this group that leads them to believe that
exceptions should only be used
where severe runtime errors require program termination
is mainly based on the notion that
the performance impact of exceptions is prohibitive.
Besides the Meyers books and my trusty copy of "C++ FAQs",
I'm going on my intuition based on years of experience.
Am I over-indoctrinated in the use of exceptions?
Are there some warnings that I'm not heeding?
Can exceptions impact performance to the degree that my coworkers claim?
I'd like to hear some anti-exception thoughts, if they exist.

Your question is very vague.

No, the exception handling mechanism should *not* be used
for normal flow control. It should only be used
for expected but unpredictable and unpreventable events
that are rare *exceptions* to the normal result.
The exception handling mechanism was designed to be implemented
so that *no* additional overhead is required
if an exception is not thrown.
If an exception is thrown, a great deal of extra computation
may be required to handle it.

The exception handling mechanism should *not* be used
to detect and locate programming errors (bugs).
Programming errors are *not* exceptions
because they are not expected
and are both predictable and preventable once detected.

Exceptions are not always errors.
They may be events, such as running out of memory,
over which your program has no control.


Listen to your coworkers.
From what you have told us,
it appears that they know what they are talking about.
 
E

E. Robert Tisdale

Cy said:
Scott Brady Drummonds wrote:
[snip]

I never could figure out how
use of exceptions could cause such big run time errors.
If you use them properly as error handlers
rather than control structures

Although Scott doesn't say this,
I suspect that this is what his coworkers are complaining about.
they won't be invoked often enough to run up much execution time.
And if you avoid exception specifications
(which are basically useless anyway)
they don't have much overhead at all.

The assumption is that exceptions are rarely thrown.
 
I

Igor Okulist

they won't be invoked often enough to run up much execution time
What is I hear that to setup try block does cost CPU time?
Which actually makes sense to me, since the program has to setup
unwind information.

I would imagine your program have more or less localized exception
handling, as opposed to :

main()
{
try{
doeverythingelse();
}catch(...){
printf("caught exception");
}

Anybody wants to add more details on this issue?

Actually the biggest issue with exceptions for me is that you cannot
through them across library boundary, especially if the libs are done
with different compilers. (although its not exactly exceptions fault, the
problem still stands)

Igor

E. Robert Tisdale said:
Cy said:
Scott Brady Drummonds wrote:
[snip]

I never could figure out how
use of exceptions could cause such big run time errors.
If you use them properly as error handlers
rather than control structures

Although Scott doesn't say this,
I suspect that this is what his coworkers are complaining about.
they won't be invoked often enough to run up much execution time.
And if you avoid exception specifications
(which are basically useless anyway)
they don't have much overhead at all.

The assumption is that exceptions are rarely thrown.
 
M

Markus Elfring

And if you avoid exception specifications (which are basically useless
anyway) they don't have much overhead at all.

I disagree.
- An interface designer can specify the expected error values so that
the developer or programmer must adhere to such restrictions in the
implementation.

- If the an exception specification is omitted, the compiler (that
does not perform inter-procedural analysis) must assume that every
possible exception can be thrown and must be prepared to generate code
for the handling of stack unwinding and related stuff. This detail can
be optimized if you add "throw()" to your functions and methods
because no exceptions will be thrown.

Regards,
Markus
 
L

Lionel B

Markus said:
I disagree.

I agree (with your disagreement).

I recently benchmarked some highly optimised low-level number-crunching
code with and without exception handling [floating point exception
trapping was not enabled in either case]. Even when no exceptions were
being thrown there was a performance hit of about 20% with exception
handling enabled [with or without explicit exception specification -
this didn't seem to make much difference].
 
M

Markus Elfring

Besides the Meyers books and my trusty copy of "C++ FAQs", I'm going on my
intuition based on years of experience. Am I over-indoctrinated in the use
of exceptions? Are there some warnings that I'm not heeding? Can
exceptions impact performance to the degree that my coworkers claim? I'd
like to hear some anti-exception thoughts, if they exist.

Would you like to develop for evironments with very limited resources?
How do you think about this article by P. J. Plauger?

Embedded C++: An Overview
Is EC++ the diet pill that will shrink C++ down to size for embedded applications?
http://www.ghs.com/download/ec++.pdf
 
L

Lionel B

E. Robert Tisdale said:
The exception handling mechanism was designed to be implemented
so that *no* additional overhead is required
if an exception is not thrown.

Not sure quite what you mean by "was designed to be implemented"... in
my experience (well, mainly with gcc) even if exceptions are not thrown
performance is nevertheless (quite substantially) impacted by the
exception handling mechanism. It is difficult to see how this could not
be the case: even if exceptions are not thrown the compiler has to
allow for the possiblity that exceptions *might* be thrown. This
implies at the very least that it must store stack unwinding
information somewhere, which will surely incur an overhead.
 
A

Alf P. Steinbach

* Lionel B:
Not sure quite what you mean by "was designed to be implemented"... in
my experience (well, mainly with gcc) even if exceptions are not thrown
performance is nevertheless (quite substantially) impacted by the
exception handling mechanism. It is difficult to see how this could not
be the case: even if exceptions are not thrown the compiler has to
allow for the possiblity that exceptions *might* be thrown. This
implies at the very least that it must store stack unwinding
information somewhere, which will surely incur an overhead.

Well, no, I think all the necessary _dynamic_ stack unwinding information is
present in the chain of return adresses which you have anyway. All you
have to do, in theory, is to compare the current execution address plus
each return address to a statically compiled table of exception handlers,
and check the exception type against ditto statically compiled information.
At least as far as I can see, not having implemented a C++ compiler.

But that's theory.

Reality is something else, where e.g. Visual C++ supports native
Windows SEH exceptions so that execution of the outermost 'try' in
a function is not a no-op, and where an exception can pass up through a
linkage boundary (in standard C++ there is only the one program, in real C++
there are dynamic libraries). Your comment about gcc is a bit vague, though.
If I recall correctly the internal exception mechanism in gcc was changed in
some version, but whether it was from dynamic to more static table-driven or
opposite I don't recall -- presumably each has its pros and cons.
 
G

Gianni Mariani

Scott said:
Hi, all,

I just got out of a meeting with a team of software developers that I
recently joined as they are staffing to create a medium-sized project
(potentially all of which will be written in C++). From my experience and
readings, I've come to this group indoctrinated to use exceptions for error
handling. The experience in this group that leads them to believe that
exceptions should only be used where severe runtime errors require program
termination is mainly based on the notion that the performance impact of
exceptions is prohibitive.

Just for the record. If your program is incapable of continuing, then it
should abort at the point where the error is detected. This is what
assert() is for.
Besides the Meyers books and my trusty copy of "C++ FAQs", I'm going on my
intuition based on years of experience. Am I over-indoctrinated in the use
of exceptions? Are there some warnings that I'm not heeding? Can
exceptions impact performance to the degree that my coworkers claim? I'd
like to hear some anti-exception thoughts, if they exist.


The biggest problem I have with exception use is that it's nigh
impossible to figure out what went wrong when somthing bad happens.
This may be an implementation issue rather than a specification issue
but without a reliable way of figuring out what happened when, I really
can't reccomend it's use.

e.g. consider this mock up code (just one example)


struct X
{
void F1( X * x ) throw()
{
x->F2(); // somwhere we need to call F2.
}

virtual void F2() = 0;
};

struct Y : X
{

virtual void F2()
{
// ... bad thing happened

throw int(1); // post-mortem does not show this line at all
}
};

int main()
{
Y y[1];

X * x = y;

x->F1( x );
}

The program dumps core because the default "unexpected()" is called in
the context of F1 where it promptly dumps core. All the knowledge of
what happened is lost. No stack frames, no thrown object, NADA.


#0 0x401545c1 in kill () from /lib/libc.so.6
#1 0x40154355 in raise () from /lib/libc.so.6
#2 0x4015589b in abort () from /lib/libc.so.6
#3 0x400bb1cd in __gnu_cxx::__verbose_terminate_handler ()
at ../../../../gcc-3.4.0/libstdc++-v3/libsupc++/vterminate.cc:96
#4 0x400b9220 in __cxxabiv1::__terminate (handler=0x400bb0dc
<__gnu_cxx::__verbose_terminate_handler()>)
at ../../../../gcc-3.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:43
#5 0x400b9258 in std::terminate () at
.../../../../gcc-3.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:53
#6 0x400b926c in __cxxabiv1::__unexpected (handler=0x400b9238
<std::terminate()>)
at ../../../../gcc-3.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:59
#7 0x400b9162 in __cxa_call_unexpected (exc_obj_in=0x8049b28)
at ../../../../gcc-3.4.0/libstdc++-v3/libsupc++/eh_personality.cc:486
#8 0x0804876a in X::F1 ()
#9 0x08048728 in main ()
 
L

Lionel B

Gianni said:
Just for the record. If your program is incapable of
continuing, then it should abort at the point where
the error is detected. This is what assert() is for.

And if your "program" is actually a library which other (people's)
programs are going to link to...?

Another viewpoint is that if your program is incapable of continuing -
at least for any other reason than physical limitations (head crash,
CPU explodes, etc.) - then that is programmer error.

As an example, I have written a number of C++ library routines to be
called from the Gauss linear algebra system (think Matlab but
clunkier). If my library code aborts... so does Gauss! My users do not
appreciate this. So I use exceptions to recover elegantly from
(unforseeable) situations such as resource exhaustion, then deliver an
informative explanatory message to the user ("Out of memory. Yes YOU
used it all up. Pig.", etc.).
 
L

Lionel B

Gianni said:
Just for the record. If your program is incapable of
continuing, then it should abort at the point where
the error is detected. This is what assert() is for.

And if your "program" is actually a library which other (people's)
programs are going to link to...?

Another viewpoint is that if your program is incapable of continuing -
at least for any other reason than physical limitations (head crash,
CPU explodes, etc.) - then that is programmer error.

As an example, I have written a number of C++ library routines to be
called from the Gauss linear algebra system (think Matlab but
clunkier). If my library code aborts... so does Gauss! My users do not
appreciate this. So I use exceptions to recover elegantly from
(unforseeable) situations such as resource exhaustion, then deliver an
informative explanatory message to the user ("Out of memory. Yes YOU
used it all up. Pig.", etc.).
 
L

Lionel B

Gianni said:
Just for the record. If your program is incapable of
continuing, then it should abort at the point where
the error is detected. This is what assert() is for.

And if your "program" is actually a library which other (people's)
programs are going to link to...?

Another viewpoint is that if your program is incapable of continuing -
at least for any other reason than physical limitations (head crash,
CPU explodes, etc.) - then that is programmer error.

As an example, I have written a number of C++ library routines to be
called from the Gauss linear algebra system (think Matlab but
clunkier). If my library code aborts... so does Gauss! My users do not
appreciate this. So I use exceptions to recover elegantly from
(unforseeable) situations such as resource exhaustion, then deliver an
informative explanatory message to the user ("Out of memory. Yes YOU
used it all up. Pig.", etc.).
 
L

Lionel B

Gianni said:
Just for the record. If your program is incapable of
continuing, then it should abort at the point where
the error is detected. This is what assert() is for.

And if your "program" is actually a library which other (people's)
programs are going to link to...?

Another viewpoint is that if your program is incapable of continuing -
at least for any other reason than physical limitations (head crash,
CPU explodes, etc.) - then that is programmer error.

As an example, I have written a number of C++ library routines to be
called from the Gauss linear algebra system (think Matlab but
clunkier). If my library code aborts... so does Gauss! My users do not
appreciate this. So I use exceptions to recover elegantly from
(unforseeable) situations such as resource exhaustion, then deliver an
informative explanatory message to the user ("Out of memory. Yes YOU
used it all up. Pig.", etc.).
 
C

Cy Edmunds

Markus Elfring said:
I disagree.
- An interface designer can specify the expected error values so that
the developer or programmer must adhere to such restrictions in the
implementation.

- If the an exception specification is omitted, the compiler (that
does not perform inter-procedural analysis) must assume that every
possible exception can be thrown and must be prepared to generate code
for the handling of stack unwinding and related stuff. This detail can
be optimized if you add "throw()" to your functions and methods
because no exceptions will be thrown.

Regards,
Markus

http://www.gotw.ca/publications/mill22.htm
 
C

Cy Edmunds

Igor Okulist said:
What is I hear that to setup try block does cost CPU time?
Which actually makes sense to me, since the program has to setup
unwind information.

I would imagine your program have more or less localized exception
handling, as opposed to :

main()
{
try{
doeverythingelse();
}catch(...){
printf("caught exception");
}

Anybody wants to add more details on this issue?

Actually the biggest issue with exceptions for me is that you cannot
through them across library boundary, especially if the libs are done
with different compilers. (although its not exactly exceptions fault, the
problem still stands)

Igor

[snip]

You have to compare

try{
dosomething();
} catch(...) {
fixit();
}

with

err_code = dosomething();
if (error_code)
fixit();

Both take run time although I wouldn't call it overhead -- good error
handling isn't optional. I find the former style clearer and much easier to
maintain.
 
C

Cy Edmunds

Gianni Mariani said:
Just for the record. If your program is incapable of continuing, then it
should abort at the point where the error is detected. This is what
assert() is for.



The biggest problem I have with exception use is that it's nigh impossible
to figure out what went wrong when somthing bad happens. This may be an
implementation issue rather than a specification issue but without a
reliable way of figuring out what happened when, I really can't reccomend
it's use.

e.g. consider this mock up code (just one example)


struct X
{
void F1( X * x ) throw()

Why use exception specifications? See
http://www.gotw.ca/publications/mill22.htm
{
x->F2(); // somwhere we need to call F2.
}

virtual void F2() = 0;
};

struct Y : X
{

virtual void F2()
{
// ... bad thing happened

throw int(1); // post-mortem does not show this line at all

You throw an int and then complain that exceptions don't help you trace the
problem? I assume you realize that you can throw a class instance here which
contains all the relevant post-mortem information -- or better yet,
information required to fix the problem and continue.
}
};

int main()
{
Y y[1];

X * x = y;

x->F1( x );
}

The program dumps core because the default "unexpected()" is called in the
context of F1 where it promptly dumps core. All the knowledge of what
happened is lost. No stack frames, no thrown object, NADA.

The unexpected call is a result of your using a throw specification.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,970
Members
47,526
Latest member
RoslynDavi

Latest Threads

Top