简体   繁体   English

异常处理

[英]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". 我没有得到什么,无论我抛出异常以及是否使用“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. 我可以使用“return”而不是抛出异常,但那时它是一样的。 I know stack unwinding can go even six stacks back, but so checking return value and "return" combined. 我知道堆栈展开甚至可以返回六个堆栈,但所以检查返回值和“返回”组合。

An explanation will be welcomed. 欢迎解释。

When you use a return, the stack is "unwound" unconditionally, which can conceptually be as simple as executing a single "ret" machine code instruction. 当您使用返回时,无条件地“展开”堆栈,这在概念上可以像执行单个“ret”机器代码指令一样简单。 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. 异常路径还具有构造并可能复制异常对象的任务,这可能不是微不足道的。

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. 它还涉及在堆栈中的每个较低级别中搜索错误处理程序(catch块)。 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;          
    }
}

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. 许多编译器将这种开销减少到接近零 - 但是有一些平台,特别是游戏控制台,其中可用的编译器或硬件不能很好地处理异常。

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. 这曾经足够重要,许多人选择避免它并完全禁用RTTI。 These days its so negligible that if its an issue than maybe C++ is already too high level for you ;-) 这些天它是如此微不足道,如果它的问题可能比C ++已经太高了你的水平;-)

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. 在异常和堆栈展开的传播方面,还有额外的成本,但是因为(a)你必须解开堆栈,正如你所说的那样(虽然这不是成本所在的位置)和(b)你是已经在异常路径上,无论如何额外成本可能永远不会成为问题。

Most people that complain about the costs of exception handling are thinking of how it used to be. 抱怨异常处理成本的大多数人都在考虑过去的情况。

如果您对影响异常处理对性能感兴趣,那么开始阅读的最佳位置是C ++性能技术报告 (特别是第5.4章)。

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. 我的拙见是,错误处理可能会花费更长的时间,因为它不常发生。

Most versions of exception handling add some small extra overhead to help the compliler deal with issues like scope. 大多数异常处理版本都会增加一些额外的开销,以帮助compliler处理范围等问题。 Here is an article that has an explanation. 是一篇有解释的文章。 The overhead we are talking about is very small and almost never worth worrying about. 我们谈论的开销非常小,几乎从不值得担心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM