views:

447

answers:

7

I have read that there is some overhead to using C++ exceptions for exception handling as opposed to, say, checking return values. I'm only talking about overhead that is incurred when no exception is thrown. I'm also assuming that you would need to implement the code that actually checks the return value and does the appropriate thing, whatever would be the equivalent to what the catch block would have done. And, it's also not fair to compare code that throws exception objects with 45 state variables inside to code that returns a negative integer for every error.

I'm not trying to build a case for or against C++ exceptions solely based on which one might execute faster. I heard someone make the case recently that code using exceptions ought to run just as fast as code based on return codes, once you take into account all the extra bookkeeping code that would be needed to check the return values and handle the errors. What am I missing?

+1  A: 

In .NET (if you are referring to C++/CLI), minimal overhead. As far as native C++, I would assume it's the same.

The overhead mainly comes from using exceptions as control logic, when an exception is thrown there is a higher cost than just checking for whatever would have thrown it to begin with.

Aequitarum Custos
+7  A: 

Only try/catch and try/except block take a few instructions to set up. The overhead should generally be negligible in every case except the tighest loops. But you wouldn't normally use try/catch/except in an inner loop anyway.

I would advise not to worry about this, and use a profiler instead to optimize your code where needed.

Frederik Slijkerman
Is this really true? Why is try/catch any different from a local variable or temporary that has a destructor?
Jason Orendorff
The GNU C++ compiler uses the zero–cost model by default i.e. there is no time overhead when exceptions don't occur.
Martin York
+2  A: 

It's completely implementation dependent but many recent implementations have very little or no performance overhead when exceptions aren't thrown. In fact you are right. Correctly checking return codes from all functions in code that doesn't use exceptions can be slower then doing nothing for code using exceptions.

Of course, you would need to measure the performance for your particular requirements to be sure.

Charles Bailey
+3  A: 

There is a cost associated with exception handling on some platforms and with certain compilers.

Namely, Visual Studio, when building a 32-bit target, will register a handler in every function that has local variables with non-trivial destructor. Basically, it sets up a try/finally handler.

The other technique, employed by gcc and Visual Studio targeting 64-bits, only incurs overhead when an exception is thrown (the technique involves traversing the call stack and table lookup). In cases where exceptions are rarely thrown, this can actually lead to a more efficient code, as error codes don't have to be processed.

avakar
I knew I wasn't entirely imagining things.
A: 

Nothing like actually trying the experiment:

#include <exception>

long int g_i1 = 0;
long int g_i2 = 0;

void noException() {
    g_i1 += 1;

    if (g_i1 < 0) {
    return;
    }
}

void withException() {
    g_i2 += 1;

    if (g_i2 < 0) {
        throw new std::exception();
    }
}

int main(void) {
    int i;

    for (i = 0; i < 100000000; i++) {
        // noException();
    withException();  
    }

    return 0;
}

When I had noException in the loop, my results were:

% time ./NoException
./NoException  0.53s user 0.00s system 94% cpu 0.566 total

When I had withException in the loop, my results were:

% time ./NoException
./NoException  0.97s user 0.00s system 96% cpu 1.003 total
Chip Uni
Which compiler? With optimizations on or off? At least GCC4.something with -O3 should completely remove the if() case ;-)
frunsi
See my answer to the question I mentioned as a dupe.
anon
frunsi -- I used g++ (Debian 4.3.4-6) with no optimization.
Chip Uni
well, running with no optimization _may_ be a bit unfair.
frunsi
@avakar: But this example doesn't throw an exception (unless have have a small `long int`), it's just supposed to show the performance difference if the compiler can't be certain that a code path which would throw an exception isn't executed.
Charles Bailey
I think that this example is also unfair because the if statement can be completely removed in the non-exception case as there is no difference in behaviour whether or not the if expression is true.
Charles Bailey
Also note that there need not be any exception handling code, since without an exception handler, performing `throw` is as simple as calling `std::terminate`.
avakar
Charles Bailey, thanks I realized that a few moments after posting that comment.
avakar
I took this code and made the noException return a bool (false in the exceptional case), and added a test outside the function to call `exit` if it returned false. This has better matching behaviour for the two variants. They both had identical performance on my system with optimizations on.
Charles Bailey
Thanks for running that experiment, Charles!
Chip Uni
+1  A: 

There is some overhead with exceptions (as the other answers pointed out).

But you do not have much of a choice nowadays. Try do disable exceptions in your project, and make sure that ALL dependent code and libraries can compile and run without.

Do they work with exceptions disabled?

Lets assume they do! Then benchmark some cases, but note that you have to set a "disable exceptions" compile switch. Without that switch you still have the overhead - even if the code never throws exceptions.

frunsi
A: 

Only overhead is ~6 instructions which add 2 SEH at the start of the function and leave them at the end. No matter how many try/catches you have in a thread it is always the same.

Also what is this about local variables? I hear people always complaining about them when using try/catch. I don't get it, because the deconstructors would eventually be called anyways. Also you shouldn't be letting an exception go up more then 1-3 calls.

I think the point about local variables is that it takes some more tinkering/work to figure out what to destroy when an exception is in flight as opposed to the normal case. At least, that's what I've heard. (I suppose they might be trying to keep code size down, but I'm not sure)
Marcus Lindblom