views:

167

answers:

7
+2  Q: 

Exception handling

I heard people say exception handling is a bit expensive because of the stack unwinding.

I don't get something, the stack unwinding happens whether I throw an exception and whether I use "return". So where is the difference?

If for example I get a memory problem that I can't handle - the only option is to stop the function till the I reach the area where the problem should be handled or notified. So what's my other option for throwing an exception?

I can use "return" instead of throwing exception, but then it's the same. I know stack unwinding can go even six stacks back, but so checking return value and "return" combined.

An explanation will be welcomed.

A: 

Most versions of exception handling add some small extra overhead to help the compliler deal with issues like scope. Here is an article that has an explanation. The overhead we are talking about is very small and almost never worth worrying about.

Kevin Gale
+4  A: 

When you use a return, the stack is "unwound" unconditionally, which can conceptually be as simple as executing a single "ret" machine code instruction. Under exceptions, the stack unwinding has to search for a suitable exception handler, which is a far more complex task. The exception path also has the task of constructing and probably copying the exception object, which may not be trivial.

anon
Return codes need to be checked at each level to find a suitable place to handle the error as well - the only difference is whether the compiler or the programmer generates the checking code.
Joe Gauterin
Functions do not necessarily have return coes, and programmers do not need to check them. How many people check the return value of printf(), for example?
anon
Mordachai
The C++ compiler almost certainly makes a copy of the excception object, which is why an exception object must have publically available copy constructor - see the C++ Standard, section 15.1. Also, you cannot "throw by reference".
anon
I think Mordachai meant throw by value catch by reference. At least, that's the suggestion here http://www.goingware.com/tips/parameters/exceptions.html
Randolpho
+1  A: 

There is a small "cost" for the infrastructure needed to convey exceptions in the first place. This used to be significant enough many people chose to avoid it and disable RTTI altogether. These days its so negligible that if its an issue than maybe C++ is already too high level for you ;-)

In terms of the propagation of exceptions and stack-unwinding there are additional costs but since (a) you'd have to unwind the stack anyway, as you say (although that's not really where the cost is) and (b) you're already on an exception path where the additional cost is probably never an issue anyway.

Most people that complain about the costs of exception handling are thinking of how it used to be.

Phil Nash
+2  A: 

The speed of error handling mechanisms in the case of an error is unimportant - they should be executed too infrequently to make an impact on overall program performance (they're exceptional events).

When people talk about exception handling being expensive they are talking about the effect it has on the performance of a function when that function completes without raising an exception. Many compilers reduce this overhead to near zero - but there are some platforms, notably games consoles, where either the available compilers or the hardware doesn't handle exceptions very well.

Joe Gauterin
+1  A: 

Stack unwinding is different from simply returning. It also involves a search for an error handler (a catch block) in each lower level in the stack. That's what makes it a heavy process.

That's why you should only use exceptions for truly exceptional circumstances. The warnings about exception handling are for those folks who simply see an exception as a way to deliver data higher up in the stack; folks who like to do "clever" programming. They think it's a clever way to get around a problem, but they instead create two new problems they hadn't anticipated.

In general, you're best off using exceptions (for truly exceptional circumstances) rather than return codes, as this makes your code easier to read and maintain. For example, which is easier to read and maintain?

void MyMethod()
{
    try
    {
        Method1(); 
        Method2();
        Method3();
    }
    catch(SomeException const & e) // edited per Mordachai's suggestion
    {
       // handle SomeException
    }
    catch(SomeOtherException const & e)
    {
       // handle SomeOtherException
    }
}

void MyMethod()
{
    int err;
    err = Method1();
    switch(err)
    {
        case SOMEERRORCODE:
             // handle some error code
             break;
        case SOMEOTHERERRORCODE:
             // handle some other error code
             break;    
    }
    err = Method2();
    switch(err)
    {
        case SOMEERRORCODE:
             // handle some error code
             break;
        case SOMEOTHERERRORCODE:
             // handle some other error code
             break;    
    }
    err = Method3();
    switch(err)
    {
        case SOMEERRORCODE:
             // handle some error code
             break;
        case SOMEOTHERERRORCODE:
             // handle some other error code
             break;    
    }
}
Randolpho
Why catching by pointer? Unless it is MFC...
Nemanja Trifunovic
Mordachai
In my defense: I've probably spent too long in the Java and .NET world; there I'd just catch a reference to the exception and I was trying to duplicate that. But regardless of *what* I'm catching, the point still stands: exceptions, done correctly, in general, tend to be easier to read and maintain.
Randolpho
Also, how would you catch a const reference to an exception object, anyway? Wouldn't the exception be out of scope right after it was thrown? It'd be off the stack by the time it got caught.
Randolpho
Aaand, once again, SO to the rescue: http://stackoverflow.com/questions/1654150/scope-of-exception-object-in-c
Randolpho
+1  A: 

If you are interested in the impact exception handling has on performance, the best place to start reading is the Technical Report on C++ Performance (Chapter 5.4 in particular).

Nemanja Trifunovic
+1  A: 

I suggest concentrating on quality, correctness and robustness before worrying about the performance of a program. Many users would prefer a slow working program to a fast one that faults often.

After the program is working, run a profiler and find out where the most of the time is spent. My humble opinion is that error handling can take a bit longer since it happens less frequently.

Thomas Matthews