Topic: A General Overhead Question about Exceptions
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1999/02/27 Raw View
"Jeff Greif" <jmg@trivida.com> writes:
>Thanks. I agree that exceptions thrown from the constructor of exceptions
>(meaning any thrown thing) are no problem. What about exceptions thrown
>from the destructors run during the stack unwinding of a throw? Is there a
>similarly simple model?
If a destructor called during stack unwinding exits via an
exception, terminate() is immediately called. That's a pretty
simple model. :-)
For that reason, a good design guideline is that destructors should
never exit via an exception. If an error can occur during
destruction that needs to be reported, you should try to find some
other design.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jeff Greif" <jmg@spam-me-not.trivida.com>
Date: 1999/02/25 Raw View
Conceptually at least, a straightforward implementation of exception
handling might work like this:
Each scope (stack frame or block or whatever) is associated with some kind
of data structure indicating which destructors must be run when leaving the
scope and in which order (putting the structure in the stack frame avoids
explicit cleanup code for it, and avoids having to chain together the
structures for the various scopes). This is required whether any exceptions
can be thrown or not. This structure is updated as the various objects in
the block are actually constructed (some optimizations of this process are
probably possible when it is guaranteed that no exceptions can be thrown
from this or any inner scope, e.g. if exception handling is turned off.)
Now, when an exception is thrown, the stack unwinding process must visit all
these data structures in order of containing scope (from innermost to the
scope where the catch is declared), executing the appropriate destructors).
There are various tradeoffs that may be possible to avoid a linear search
for the catch, etc, but these are overheads present only when an exception
is thrown. The cost of bookkeeping for the destructors is basically (but
not in complete detail) a property of normal execution, not exception
handling.
This discussion ignores some of the subtleties (that I don't fully
understand), like throwing exceptions from within the constructor of an
exception, etc). In any case, in this approach to exception handling, the
cost of the try-catch block is very low.
Jeff
Philip Koester inquired:
....
>This lead me to the question about overhead being added for code executed
in
>try blocks, and for code called from there and so on. That is, I got
>worried whether the whole execution of my main application thread would
slow
>down only due to this single try statement?! Apparently, some sort of
>bookkeeping is needed to keep track on all objects that need destructing
>when an exception is thrown -- does this mean this bookkeeping is done if
an
>exception is never thrown? Does it mean it's done for code that doesn't
>even reside in a try block?
>
>Or, to rephrase this question: Do exceptions cause any overhead even when
>they're not in use?
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin BONNARD <Bonnard.V@wanadoo.fr>
Date: 1999/02/25 Raw View
Jeff Greif wrote:
> This discussion ignores some of the subtleties (that I don't fully
> understand), like throwing exceptions from within the constructor of an
> exception, etc).
There is no such thing as a constructor of an exception, because there
is no such thing as an 'exception type' in C++. There are values, which
become exceptions when they are used as an argument of the throw
operator.
Other languages have separated data types and exceptions (Ada, ML).
throw X (args)
means something like:
__storage_for<X> __tmp;
new (&__tmp) X (args); // (1)
__throw<X> (__tmp);
so it is clear what appens if (1) throws: the exception is simply
propagated.
--
Valentin Bonnard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jeff Greif" <jmg@trivida.com>
Date: 1999/02/25 Raw View
Valentin,
Thanks. I agree that exceptions thrown from the constructor of exceptions
(meaning any thrown thing) are no problem. What about exceptions thrown
from the destructors run during the stack unwinding of a throw? Is there a
similarly simple model? I would imagine that if instead of chaining the
destructors of a stack frame, if you treated them as if they were nested and
each represented a scope of its own, you could handle this case?
What I was trying to say in the sentence you cite is that the picture I
presented of how exception handling might be implemented could be too
simplistic. If it were as easy as my picture, probably the compiler writers
would have been able to get it working more quickly.
Jeff
-----Original Message-----
From: Valentin BONNARD <Bonnard.V@wanadoo.fr>
Newsgroups: comp.std.c++
To: comp-std-c++@moderators.usenet.fr.net
<comp-std-c++@moderators.usenet.fr.net>; Jeff Greif <jmg@trivida.com>
Date: Thursday, February 25, 1999 3:26 AM
Subject: Re: A General Overhead Question about Exceptions
>Jeff Greif wrote:
>
>> This discussion ignores some of the subtleties (that I don't fully
>> understand), like throwing exceptions from within the constructor of an
>> exception, etc).
>
...
>
>throw X (args)
>
>means something like:
>
>__storage_for<X> __tmp;
>new (&__tmp) X (args); // (1)
>__throw<X> (__tmp);
>
>so it is clear what appens if (1) throws: the exception is simply
>propagated.
>
>--
>
>Valentin Bonnard
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Philip Koester" <kozmik@okay.net>
Date: 1999/02/24 Raw View
I'm having code of mine here resembling:
int main(int, char**)
{
return my_application().main();
}
Now, I thought it might be a good idea (in debug mode) to catch all
exceptions that might be thrown through my_application::main():
int main(int, char**)
{
try
{
return my_application().main();
}
catch (exception& e)
{
cerr << "exception caught: " << e.what() << endl;
throw;
}
catch (...)
{
cerr << "unknown exception caught" << endl;
throw;
}
}
This lead me to the question about overhead being added for code executed in
try blocks, and for code called from there and so on. That is, I got
worried whether the whole execution of my main application thread would slow
down only due to this single try statement?! Apparently, some sort of
bookkeeping is needed to keep track on all objects that need destructing
when an exception is thrown -- does this mean this bookkeeping is done if an
exception is never thrown? Does it mean it's done for code that doesn't
even reside in a try block?
Or, to rephrase this question: Do exceptions cause any overhead even when
they're not in use?
I'd really like to learn more about this,
Philip
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Dave Abrahams" <abrahams@mediaone.net>
Date: 1999/02/24 Raw View
In article <7av0js$2346$1@news.ipf.de> , "Philip Koester" <kozmik@okay.net>
wrote:
> This lead me to the question about overhead being added for code executed in
> try blocks, and for code called from there and so on. That is, I got
> worried whether the whole execution of my main application thread would slow
> down only due to this single try statement?!
Highly unlikely. Even a poor compiler which makes you pay at runtime to
enter a try block can't tell whether there is an outermost try/catch block
when compiling code in a different compilation unit.
> Apparently, some sort of
> bookkeeping is needed to keep track on all objects that need destructing
> when an exception is thrown -- does this mean this bookkeeping is done if an
> exception is never thrown? Does it mean it's done for code that doesn't
> even reside in a try block?
The answer to all of these questions is yes, but: a good compiler will do
all that bookkeeping at compile-time, leaving you with no runtime overhead
at all. The overhead is translated into tables which correlate return
addresses on the stack with exception-handling code which must be run. So
the cost is in additional data space. On the other hand, as I said before,
the compiler has to generate these tables whether or not the exception will
ever actually be caught.
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/02/24 Raw View
In article <7av0js$2346$1@news.ipf.de>, Philip Koester <kozmik@okay.net>
writes
>Or, to rephrase this question: Do exceptions cause any overhead even when
>they're not in use?
Yes, but the nature of the overhead (code size, extra data, extra
instructions executed, more stack usage etc) is entirely in the hands of
the implementor. In production level code good compiler's will charge
you very little. Unfortunately small test programs may be overwhelmed
by the extra giving you a deceptive metric.
What you need to ask yourself is the cost of any alternative mechanism
for handling runtime problems (do not forget the investment of time
required both on the first write and in future maintenance)
Francis Glassborow Chair of 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
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]