Is C faster than C++

B

Branimir Maksimovic

P.J. Plauger said:
Uh, I just tried a quick test with mingw (gcc V3.2) under Windows.
Compiled as C++, a smallish program is 100,000 bytes bigger than
when compiled as C.

Perhaps that was because headers have some #ifdef __cplusplus and added
some additional libraries , but I've tested with trivial example.

bmaxa@MAXA ~
$ g++ -Wall test.c baz.c -o test

bmaxa@MAXA ~
$ gcc -Wall test.c baz.c -o testc

bmaxa@MAXA ~
$ ls -l
total 17
-rw-r--r-- 1 bmaxa Administ 14 Sep 30 17:20 baz.c
-rw-r--r-- 1 bmaxa Administ 174 Sep 30 18:58 test.c
-rwxr-xr-x 1 bmaxa Administ 15879 Sep 30 19:18 test.exe
-rwxr-xr-x 1 bmaxa Administ 15879 Sep 30 19:18 testc.exe

bmaxa@MAXA ~
$ nm test.exe > test.nm

bmaxa@MAXA ~
$ nm testc.exe > testc.nm

bmaxa@MAXA ~
$ ls -l *.nm
-rw-r--r-- 1 bmaxa Administ 7834 Sep 30 19:19 test.nm
-rw-r--r-- 1 bmaxa Administ 7822 Sep 30 19:19 testc.nm

bmaxa@MAXA ~
$ strip test*.exe

bmaxa@MAXA ~
$ ls -l
total 15
-rw-r--r-- 1 bmaxa Administ 14 Sep 30 17:20 baz.c
-rw-r--r-- 1 bmaxa Administ 174 Sep 30 18:58 test.c
-rwxr-xr-x 1 bmaxa Administ 5632 Sep 30 19:19 test.exe
-rw-r--r-- 1 bmaxa Administ 7834 Sep 30 19:19 test.nm
-rwxr-xr-x 1 bmaxa Administ 5632 Sep 30 19:19 testc.exe
-rw-r--r-- 1 bmaxa Administ 7822 Sep 30 19:19 testc.nm

bmaxa@MAXA ~
$ diff test.exe testc.exe
Binary files test.exe and testc.exe differ

bmaxa@MAXA ~
$ cat test.c baz.c
#include <stdlib.h>
#include <stdio.h>

void baz();
void bar();
void foo();

int main()
{
printf("\n");
foo();
return 0;
}

void foo()
{
bar();
}
void bar()
{
baz();
}

void baz(){}


bmaxa@MAXA ~
$ uname -a
MINGW32_NT-5.1 MAXA 1.0.10(0.46/3/2) 2004-03-15 07:17 i686 unknown

It is same if I first compiled baz into object file and then linked it with
test.o.
So I guess that some additional libraries were linked.

Greetings, Bane.
 
D

Dave Rahardja

throw() wouldn't help.
To quote part of 15.5.1:
"An implementation is not permitted to finish stack unwinding prematurely
based on a determination that the unwind process will eventually cause
a call to terminate()."
[snip]

I've just investigated further. Exception specification makes run time
overhead to function
only if function throws or calls function that does not have throw()
specification.

This has also been my experience. The overhead of non-throwing functions is
exactly ZERO, both in run time code and in data space.

Here is a trivial C and C++ program:

--- C program ---

int f(int i)
{
return i * 2;
}

int main()
{
return f(1);
}

--- C++ program ---

int f(int i) throw()
{
return i * 2;
}

int main()
{
try {
return f(1);
} catch (...) {
return 1;
}
}

---

Under Microsoft's VC++ .NET, both programs compile to exactly the same size of
22,016 bytes (under the Release settings), with or without the throw() clause.

To see the effect of the declaration of f() when the compiler has no access to
the code during the compilation of main(), I did the following experiment:

In the C++ program, splitting out f() to a different file and declaring it

extern "C" int f(int);

causes no change to the final program size, which indicates that the exception
handling mechanism has been successfully suppressed. However, declaring it

int f(int);

and compiling f() as a C++ function causes the build to bloat to 26,624 bytes.
Examining the map file shows that execption handling routines have been added,
accounting for the bloat. Changing the declaration to

int f(int) throw();

brings the size back down to 20,016 bytes, suggesting that exception handling
has been completely removed.

With that quick exercise it is easy to see that exception handling overhead is
exactly _zero_ with MSVC++ .NET when functions are properly declared throw().
Furthermore, MSVC is smart enough to figure out that extern "C" functions do
not throw.


My experience with the embedded compiler that I use daily has been the same:
the exception handling overhead for properly-declared code is not only
trivial, it is _zero_.

However, I will admit again that the decision to assume that functions with no
throw clause can "throw anything" instead of "throw nothing" makes it very
difficult for compilers to automatically elide the generation of exception
handling infrastructure. Declaring functions throw() when it really doesn't
throw anything is good practice whenever resources are at a premium.


Yes, the iostream library accounts for most of the immense bloat that C++
programs have, but C++ as a language is perfectly viable (especially on
embedded targets) without that library; there is nothing _inherently_
inefficient with the language itself.
 
P

P.J. Plauger

With that quick exercise it is easy to see that exception handling
overhead is
exactly _zero_ with MSVC++ .NET when functions are properly declared
throw().
Furthermore, MSVC is smart enough to figure out that extern "C" functions
do
not throw.

My experience with the embedded compiler that I use daily has been the
same:
the exception handling overhead for properly-declared code is not only
trivial, it is _zero_.

However, I will admit again that the decision to assume that functions
with no
throw clause can "throw anything" instead of "throw nothing" makes it very
difficult for compilers to automatically elide the generation of exception
handling infrastructure. Declaring functions throw() when it really
doesn't
throw anything is good practice whenever resources are at a premium.

So if you declare *every* function either as extern "C" or with a
throw() qualifier, you can match the lower overhead of native C
code, at least with *some* compilers. But the least lapse in this
style -- such as writing C++ the way all the books tell you to --
and you get the bloat of exception handling whether or not you
use it.
Yes, the iostream library accounts for most of the immense bloat that C++
programs have, but C++ as a language is perfectly viable (especially on
embedded targets) without that library; there is nothing _inherently_
inefficient with the language itself.

So if you don't use the library *designed* for use with Standard
C++, the way all the books tell you, you can match the lower overhead
of native C style, at least with *some* compilers.

Now please review your words and consider whether there is anything
*inherently* inefficient with the language itself. Asymptotic behavior
doesn't mean much in the world of real programming.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
D

Dave Rahardja

So if you declare *every* function either as extern "C" or with a
throw() qualifier, you can match the lower overhead of native C
code, at least with *some* compilers. But the least lapse in this
style -- such as writing C++ the way all the books tell you to --
and you get the bloat of exception handling whether or not you
use it.
So if you don't use the library *designed* for use with Standard
C++, the way all the books tell you, you can match the lower overhead
of native C style, at least with *some* compilers.

Now please review your words and consider whether there is anything
*inherently* inefficient with the language itself. Asymptotic behavior
doesn't mean much in the world of real programming.

It's obvious that we're not going to convince each other in this matter. It
appears that our views of what constitutes a fair comparison differ
considerably.

My experience with C++ in both the desktop and embedded worlds is that the
overhead for _equivalent_ behavior is zero. Each overhead in C++ comes with an
additional feature, which C does not afford you. C++ defaults to a larger set
of features that you can "turn off", while C starts out with a basic set to
which you must add. In my mind, a fair comparison involves turning off
features in your C++ program to match the behavior of the C program that
you're comparing it to. Anything else is not a fair comparison in my mind, but
you obviously think that that's too much to ask in the "real world".

Maybe I can convince others, if not you, that what you consider "asymptotic
behavior" is par for the course in many application domains, including mine
(embedded code), although for most applications, the overhead associated with
the "traditional" coding style is more than made up for by the features that
C++ brings to the table. However, C-equivalent efficiency is attainable by
correct specification.

I stand by my statements and observations (and take advantage of them daily),
although you probably disagree with them.

I do concede that the two areas you highlight--default exception handling
behavior and iostreams--contribute to significant data and code bloat in C++
programs and must be aggressively managed for efficiency-critical code.

-dr
 
P

P.J. Plauger

It's obvious that we're not going to convince each other in this matter.
It
appears that our views of what constitutes a fair comparison differ
considerably.

My experience with C++ in both the desktop and embedded worlds is that the
overhead for _equivalent_ behavior is zero. Each overhead in C++ comes
with an
additional feature, which C does not afford you. C++ defaults to a larger
set
of features that you can "turn off", while C starts out with a basic set
to
which you must add. In my mind, a fair comparison involves turning off
features in your C++ program to match the behavior of the C program that
you're comparing it to. Anything else is not a fair comparison in my mind,
but
you obviously think that that's too much to ask in the "real world".

In the usual sense, yes. What's advertised for C++ is: if you don't
use it, you don't pay for it. What you admit above, and several others
have demonstrated, is that you have to "use" quite a bit of stuff from
exception handling to *not* pay for it. Specifically, you have to make
liberal use of throw specifications. (Or you can declare all of your
functions extern "C", don't use any C++ functions from the library,
and hence "turn off" cross-module type checking in the bargain.)

And BTW, not all implementations of Standard C++ eliminate all space
and time overheads for exceptions even if you do the above. It's
well over a decade now since compilers started shipping with exceptions,
and that's still the state of the art.

So yes, I do consider my comparisons fair, and yes, I think that's
too much to ask in the real world. Having said that, I observe that
some C++ compilers have a switch that disables exception handling
unilaterally. All you need then is a library that can tolerate
such antics. We happen to provide one called EC++. It's part of our
standard library package, alongside the Standard C++ library. But
the same people who argue that C++ has zero overheads usually foam
at the mouth at the mention of subsetting...
Maybe I can convince others, if not you, that what you consider
"asymptotic
behavior" is par for the course in many application domains, including
mine
(embedded code), although for most applications, the overhead associated
with
the "traditional" coding style is more than made up for by the features
that
C++ brings to the table.

Please note that I made exactly this point in my first posting.
My major point was that it's a mark of zealotry to deny that
overheads do exist.
However, C-equivalent efficiency is attainable by
correct specification.

For some implementations. If you know what "correct" means.
And if you do your best to write C code masquerading as C++.
Please also note that this style is fragile. All you need is
one maintainer who's not clued in to the correct style to
add one innocent call (possibly copied from a reputable text
book) and suddenly bloat up an executable.
I stand by my statements and observations (and take advantage of them
daily),
although you probably disagree with them.

Actually, I don't.
I do concede that the two areas you highlight--default exception handling
behavior and iostreams--contribute to significant data and code bloat in
C++
programs and must be aggressively managed for efficiency-critical code.

Yep. And it's the "aggressively managed" part that puts the lie
to the opinion that prompted my first posting:

: : ...
: Anything you believe about "hidden costs" are similar to your beliefs
: about UFOs and gods. Ie: non-existent.

The hidden costs are real if you have to work hard to drag
them out of hiding before you can exorcise them.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
D

Dave Rahardja

Yep. And it's the "aggressively managed" part that puts the lie
to the opinion that prompted my first posting:

: : ...
: Anything you believe about "hidden costs" are similar to your beliefs
: about UFOs and gods. Ie: non-existent.

The hidden costs are real if you have to work hard to drag
them out of hiding before you can exorcise them.

-dr
 
P

P.J. Plauger

There exists at least one implementation where, with
"aggressively managed" code, you can reduce exception
overhead to zero.

Therefore, the "hidden costs" of using C++ instead of C
are nonexistent.

If you're convinced that this is a logically tight
argument, then you're right, I'll never convince
you otherwise. Please look up the definition of
zealotry.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
D

Dave Rahardja

There exists at least one implementation where, with
"aggressively managed" code, you can reduce exception
overhead to zero.

Therefore, the "hidden costs" of using C++ instead of C
are nonexistent.

If you're convinced that this is a logically tight
argument, then you're right, I'll never convince
you otherwise. Please look up the definition of
zealotry.

PJ, please stop putting words in my mouth, get off your high horse about
zealotry, and listen for a change. Instead of that asinine sequence of
arguments that you wrote, what I said was:

- C++ has features "turned on" by default that _do_ add inefficiencies in the
code. These inefficiencies afford features such as exception handling that do
not exist in C without manual addition.

- These features can be turned off by conscientiously managing your code (or
even managing your compiler switches), thus allowing your C++ code to match
the efficiency of C.

Notice that nowhere in my statements have I said that C++ overhead is
"nonexistent". I said that C++ code is not /necessarily/ less efficient than
C.

We are always dependent on compiler implementation for the proper generation
of our code. Just because _not all_ compilers support a standard construct
doesn't mean that the construct is worthless, or not a good practice. As far
as I can tell, the MSVC and g++ compilers (as well as my embedded compiler,
Diab) support the suppression of exception handling via the throw()
specification. That seems to be a large enough base of compiler installations
to me. How large of a base would you like to see before a compiler's
implementation becomes more than a curiosity in your eyes?

Having said all that, in most applications the overhead caused by leaving the
C++ features "on" is not significant. Where they do count, such as in the
real-time embedded world that I live in, aggressive management of code is par
for the course, not just for C++ overhead reasons, but for other efficiency
reasons such as type conversions, word sizes, and hardware considerations.

Look: I understand your arguments and agree with most of them--and it seems
that the converse is true as well. Our differences lie in the extent to which
we are willing to advocate code management to (re)gain efficiencies in C++. If
that makes you want to use a dismissive label like "zealot" on me, then I at
least claim to be a _practical_ zealot, because I practice just that sort of
"zealotry" in efficiency-sensitive portions of my code every day, with
positive results. Your mileage may vary.

-dr
 
P

P.J. Plauger

PJ, please stop putting words in my mouth, get off your high horse about
zealotry, and listen for a change. Instead of that asinine sequence of
arguments that you wrote, what I said was:

- C++ has features "turned on" by default that _do_ add inefficiencies in
the
code. These inefficiencies afford features such as exception handling that
do
not exist in C without manual addition.

- These features can be turned off by conscientiously managing your code
(or
even managing your compiler switches), thus allowing your C++ code to
match
the efficiency of C.

And that's where I part company with your quibble. There's
nothing in the C++ Standard that requires the kind of
efficiencies you claim, and in fact not all compilers
provide them. There's an important missing qualifier here.
Notice that nowhere in my statements have I said that C++ overhead is
"nonexistent".

But that indeed was what was asserted at the beginning of
this thread, and defended in various ways by you and others.
Your first post emphasized the phrase "exactly zero" three
times, while carefully decorating it with qualifiers.
There are important *disguised* qualifiers there.
I said that C++ code is not /necessarily/ less efficient
than
C.

And I've agreed that, if you work at it and if you have a
suitable compiler, you can achieve that goal for some
class of programs.
We are always dependent on compiler implementation for the proper
generation
of our code. Just because _not all_ compilers support a standard construct
doesn't mean that the construct is worthless, or not a good practice.

And I didn't say that. It's not a worthless practice; it can
be "good" if carefully enforced.
As
far
as I can tell, the MSVC and g++ compilers (as well as my embedded
compiler,
Diab) support the suppression of exception handling via the throw()
specification. That seems to be a large enough base of compiler
installations
to me. How large of a base would you like to see before a compiler's
implementation becomes more than a curiosity in your eyes?

My experiments with gcc are not as unequivocally positive as
yours. Nor is it true of all the embedded compilers I've
encountered. And I've never dubbed the "throw()" practice a
mere curiosity. I observed instead that:

a) It violates the principle that those who no nothing about
a feature (exceptions in this case) don't pay for it.

b) It's a fragile programming technique to require widespread
decoration of function declarations.

c) Even then, it's not universally guaranteed to eliminate
*all* space and time overheads with all compilers.

Those are important, practical, qualifiers.
Having said all that, in most applications the overhead caused by leaving
the
C++ features "on" is not significant.

And I pointed that out in my first posting.
Where they do count, such as in the
real-time embedded world that I live in, aggressive management of code is
par
for the course, not just for C++ overhead reasons, but for other
efficiency
reasons such as type conversions, word sizes, and hardware considerations.

Well, there's aggressive and there's aggressive, in my book.
Doing the obvious to save time and space is par for the
course. Doing magic by rote is fragile.
Look: I understand your arguments and agree with most of them--and it
seems
that the converse is true as well. Our differences lie in the extent to
which
we are willing to advocate code management to (re)gain efficiencies in
C++. If
that makes you want to use a dismissive label like "zealot" on me, then I
at
least claim to be a _practical_ zealot, because I practice just that sort
of
"zealotry" in efficiency-sensitive portions of my code every day, with
positive results. Your mileage may vary.

My charge of zealotry is to the OP, who proclaimed that such
overheads are nonexistent. But I have almost as much problem
with apologists who seem to say, "Well, he's not completely
crazy *all* the time." (This brouhaha reminds me of the
elderly lady who calls the cops, complaining that a man
across the street is behaving indecently before his window.
The cop looks and sees nothing. "Stand on the bed!" she
insists.)

The fundamental issue is whether programming in C++ yields
programs that are larger and slower than comparable programs
written in C. In my extensive experience, the simple answer
is yes. The most prudent course for a project manager is to
assume 5 to 15 per cent overheads, and take for granted that
the benefits of C++ will justify the extra costs. I went
through a similar period with C a few decades ago, selling
it against assembly language. I agree the overheads can be
managed, often significantly reduced; and it's worth teaching
people how to do so. But pretending that the problem doesn't
exist at all does not help our credibility with a rightly
critical audience of potential new users.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
D

Dave Rahardja

The fundamental issue is whether programming in C++ yields
programs that are larger and slower than comparable programs
written in C. In my extensive experience, the simple answer
is yes. The most prudent course for a project manager is to
assume 5 to 15 per cent overheads, and take for granted that
the benefits of C++ will justify the extra costs. I went
through a similar period with C a few decades ago, selling
it against assembly language. I agree the overheads can be
managed, often significantly reduced; and it's worth teaching
people how to do so. But pretending that the problem doesn't
exist at all does not help our credibility with a rightly
critical audience of potential new users.

Now this I can agree with. Let's leave it at that, shall we?

-dr
 
B

Branimir Maksimovic

Dave said:
If
exception
handling is not required, we can properly declare non-throwing functions
with
the throw() specification, or resort to compiler switches. I also imagine
that
a C++ compiler can assume that C functions declared extern "C" do not
throw.


throw() wouldn't help.
To quote part of 15.5.1:
"An implementation is not permitted to finish stack unwinding prematurely
based on a determination that the unwind process will eventually cause
a call to terminate()."
[snip]

I've just investigated further. Exception specification makes run time
overhead to function
only if function throws or calls function that does not have throw()
specification.

This has also been my experience. The overhead of non-throwing functions is
exactly ZERO, both in run time code and in data space.
........
With that quick exercise it is easy to see that exception handling overhead is
exactly _zero_ with MSVC++ .NET when functions are properly declared throw().
Furthermore, MSVC is smart enough to figure out that extern "C" functions do
not throw.


My experience with the embedded compiler that I use daily has been the same:
the exception handling overhead for properly-declared code is not only
trivial, it is _zero_.

However, I will admit again that the decision to assume that functions with no
throw clause can "throw anything" instead of "throw nothing" makes it very
difficult for compilers to automatically elide the generation of exception
handling infrastructure. Declaring functions throw() when it really doesn't
throw anything is good practice whenever resources are at a premium.

Yes, throw() specification seems to be the best practice, because
it completely eliminates exception code and data both on linux and
windows with gcc, too. Without them even C compiled as C++ has overhead
on linux. One thing more , for gcc extern "C" functions have to be
declared throw() as well. On windows && gcc,every function that have
destructor(s) (and there are almost no C++ programs that doesn't have
auto objects in functions)executed has big run time overhead
(entry/exit exception code added).
So, mister P.J.Plauger is generaly right, we have to put lot's of
throw()
specifications in order to avoid either code bloat(linux) or run time
penalty
and code bloat(windows), even with same compiler on different
platforms.

Greetings, Bane.
 
G

Greg

Branimir said:
Dave said:
If
exception
handling is not required, we can properly declare non-throwing functions
with
the throw() specification, or resort to compiler switches. I also imagine
that
a C++ compiler can assume that C functions declared extern "C" do not
throw.


throw() wouldn't help.
To quote part of 15.5.1:
"An implementation is not permitted to finish stack unwinding prematurely
based on a determination that the unwind process will eventually cause
a call to terminate()."
[snip]

I've just investigated further. Exception specification makes run time
overhead to function
only if function throws or calls function that does not have throw()
specification.

This has also been my experience. The overhead of non-throwing functions is
exactly ZERO, both in run time code and in data space.
.......
With that quick exercise it is easy to see that exception handling overhead is
exactly _zero_ with MSVC++ .NET when functions are properly declared throw().
Furthermore, MSVC is smart enough to figure out that extern "C" functions do
not throw.


My experience with the embedded compiler that I use daily has been the same:
the exception handling overhead for properly-declared code is not only
trivial, it is _zero_.

However, I will admit again that the decision to assume that functions with no
throw clause can "throw anything" instead of "throw nothing" makes it very
difficult for compilers to automatically elide the generation of exception
handling infrastructure. Declaring functions throw() when it really doesn't
throw anything is good practice whenever resources are at a premium.

Yes, throw() specification seems to be the best practice, because
it completely eliminates exception code and data both on linux and
windows with gcc, too. Without them even C compiled as C++ has overhead
on linux. One thing more , for gcc extern "C" functions have to be
declared throw() as well. On windows && gcc,every function that have
destructor(s) (and there are almost no C++ programs that doesn't have
auto objects in functions)executed has big run time overhead
(entry/exit exception code added).
So, mister P.J.Plauger is generaly right, we have to put lot's of
throw()
specifications in order to avoid either code bloat(linux) or run time
penalty
and code bloat(windows), even with same compiler on different
platforms.

Greetings, Bane.

There are some compilers that have "zero runtime overhead" exception
handling; but the tradeoff they make is in size. Exception support can
add significantly to the size of compiled code.

I don't see how a throw() specification would be likely to eliminate
any exception processing overhead. After all, a throw() specification
is no guarantee that the function will not throw an exception. It only
guarantees that a caller will never be able to catch an exception
thrown during a call to that routine [because the program will have
stopped running]. And in order to provide this guarantee the compiler
must add exception processing logic to a function with a throw()
specification just to make sure that no thrown exceptions are allowed
to escape.

In short, to eliminate exception overhead really requires going outside
the syntax defined by the language and to use use a pragma or an other
compiler-dependent way to disable the feature.

Greg
 
B

Branimir Maksimovic

Greg said:
Branimir said:
Dave said:
If
exception
handling is not required, we can properly declare non-throwing functions
with
the throw() specification, or resort to compiler switches. I also imagine
that
a C++ compiler can assume that C functions declared extern "C" do not
throw.


throw() wouldn't help.
To quote part of 15.5.1:
"An implementation is not permitted to finish stack unwinding prematurely
based on a determination that the unwind process will eventually cause
a call to terminate()."

[snip]

I've just investigated further. Exception specification makes run time
overhead to function
only if function throws or calls function that does not have throw()
specification.

This has also been my experience. The overhead of non-throwing functions is
exactly ZERO, both in run time code and in data space.
.......
With that quick exercise it is easy to see that exception handling overhead is
exactly _zero_ with MSVC++ .NET when functions are properly declared throw().
Furthermore, MSVC is smart enough to figure out that extern "C" functions do
not throw.


My experience with the embedded compiler that I use daily has been the same:
the exception handling overhead for properly-declared code is not only
trivial, it is _zero_.

However, I will admit again that the decision to assume that functions with no
throw clause can "throw anything" instead of "throw nothing" makes it very
difficult for compilers to automatically elide the generation of exception
handling infrastructure. Declaring functions throw() when it really doesn't
throw anything is good practice whenever resources are at a premium.

Yes, throw() specification seems to be the best practice, because
it completely eliminates exception code and data both on linux and
windows with gcc, too. Without them even C compiled as C++ has overhead
on linux. One thing more , for gcc extern "C" functions have to be
declared throw() as well. On windows && gcc,every function that have
destructor(s) (and there are almost no C++ programs that doesn't have
auto objects in functions)executed has big run time overhead
(entry/exit exception code added).
So, mister P.J.Plauger is generaly right, we have to put lot's of
throw()
specifications in order to avoid either code bloat(linux) or run time
penalty
and code bloat(windows), even with same compiler on different
platforms.

Greetings, Bane.

There are some compilers that have "zero runtime overhead" exception
handling; but the tradeoff they make is in size. Exception support can
add significantly to the size of compiled code.

I don't see how a throw() specification would be likely to eliminate
any exception processing overhead. After all, a throw() specification
is no guarantee that the function will not throw an exception. It only
guarantees that a caller will never be able to catch an exception
thrown during a call to that routine [because the program will have
stopped running].
Well if you look at my previous post that is what I thought about
throw().
But, it simply elliminates any trace of exception handling code and
data in gcc object files. I guess compiler knows that
eh code is not needed if every single function used in compilation unit
(declared or defined) has throw() specification.

And in order to provide this guarantee the compiler
must add exception processing logic to a function with a throw()
specification just to make sure that no thrown exceptions are allowed
to escape.

I looked at generated assembly and this is not the case.
If function has throw() specification (with or without auto objects
with destructors)and does not calls something that
can throw (it is good practice that destructors have throw()
anyway) no eh code or data is generated for that function.
It seems that that is the case with VC too (according to Dave).
So, finally this thread gaved me a good knowledge about exception
specs, and when they should be used - in functions that actually
don't throw exceptions :)
I was rather carelless about specs, but now, I know that compilers
can optimise unnedded eh code and data out when they see them.
They won't heart anyway.

Greetings, Bane.
 
D

Dave Rahardja

There are some compilers that have "zero runtime overhead" exception
handling; but the tradeoff they make is in size. Exception support can
add significantly to the size of compiled code.

Yes, I've seen at least one implementation that uses a static table of "throw
ranges" or "call sites" to deduce the objects that need to be destructed if an
exception were to be thrown at that point. Such implementations have literally
zero execution overhead (using no additional stack space and no additional
instructions in the stream). When exceptions are thrown control is passed to a
global exception handler, along with the current exception-thrower's address
and stack pointer and does the unwinding based on the tables.

The cost is obviously the substantial tables that need to be linked in
(although in most OS implementations this can be done so that the tables do
not get paged into physical memory until an exception actually occurs).
I don't see how a throw() specification would be likely to eliminate
any exception processing overhead. After all, a throw() specification
is no guarantee that the function will not throw an exception.

Actually it does (see 15.4.11), or at least /should/. However, the throw()
specification does not become part of the function type, so a function
declared throw() in one module looks identical to the linker as the function
defined without the throw-specification.

MSVC at least does give a compile-time warning if you declare a function
throw() and then proceed to throw an exception in it.

I guess the secret is to use the same declaration (i.e. header file) for the
declaration of a function everywhere in the program.
In short, to eliminate exception overhead really requires going outside
the syntax defined by the language and to use use a pragma or an other
compiler-dependent way to disable the feature.

To completely eradicate exception handling overhead once and for all you
probably need to use a compiler switch. I wonder what this does to library
functions that are specified to throw exceptions though, such as operator
new().

-dr
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top