Exception handling

750 Views Asked by At

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.

7

There are 7 best solutions below

5
On BEST ANSWER

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.

0
On

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.

0
On

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.

0
On

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.

4
On

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;          
    }
}
0
On

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).

0
On

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.