异常处理

时间:2009-12-07 16:25:35

标签: c++ exception stack-unwinding

我听说有人说由于堆栈展开,异常处理有点贵。

我没有得到什么,无论是否抛出异常以及是否使用“return”,都会发生堆栈展开。那么差异在哪里呢?

例如,如果我遇到无法处理的内存问题 - 唯一的选择是停止该功能,直到我到达应该处理或通知问题的区域。那么抛出异常的另一个选择是什么?

我可以使用“return”而不是抛出异常,但那时它是一样的。 我知道堆栈展开甚至可以返回六个堆栈,但是检查返回值和“返回”结合起来。

欢迎解释。

7 个答案:

答案 0 :(得分:7)

当您使用返回时,无条件地“展开”堆栈,这在概念上可以像执行单个“ret”机器代码指令一样简单。在异常情况下,堆栈展开必须搜索合适的异常处理程序,这是一项复杂得多的任务。异常路径还有构建和复制异常对象的任务,这可能不是一件容易的事。

答案 1 :(得分:3)

堆栈展开与简单返回不同。它还涉及在堆栈中的每个较低级别中搜索错误处理程序(catch块)。这就是使它成为一个沉重过程的原因。

这就是为什么你应该只为真正特殊情况使用例外。关于异常处理的警告是针对那些只是将异常视为在堆栈中向上传递数据的方式的人;喜欢做“聪明”编程的人。他们认为这是一个解决问题的聪明方法,但他们却创造了两个他们没有预料到的新问题。

通常,您最好使用异常(对于真正特殊的情况)而不是返回代码,因为这会使您的代码更易于阅读和维护。例如,哪个更容易阅读和维护?

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

答案 2 :(得分:2)

错误情况下错误处理机制的速度并不重要 - 它们应该很少执行,以对整体程序性能产生影响(它们是特殊的事件)。

当人们谈论异常处理成本高昂时,他们谈论的是当该函数完成而没有引发异常时,它对函数的性能的影响。许多编译器将这种开销减少到接近零 - 但是有一些平台,特别是游戏控制台,其中可用的编译器或硬件都不能很好地处理异常。

答案 3 :(得分:1)

首先传达异常所需的基础设施有一小部分“成本”。这曾经足够重要,许多人选择避免它并完全禁用RTTI。这些天它是如此微不足道,如果它的问题可能比C ++已经太高了你的水平; - )

就异常和堆栈展开的传播而言,还有额外的成本,但是因为(a)你无论如何都必须展开堆栈,正如你所说的那样(虽然这不是成本所在的地方)和(b)你已经在异常路径上,无论如何额外费用可能永远都不是问题。

大多数抱怨异常处理成本的人都在考虑过去的情况。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

我建议在担心程序的性能之前,专注于质量,正确性和稳健性。许多用户更喜欢慢速工作程序,而不是经常出错的快速程序。

程序运行后,运行一个分析器,找出大部分时间花在哪里。我的拙见是,错误处理可能会花费更长的时间,因为它不常发生。

答案 6 :(得分:0)

大多数版本的异常处理都会增加一些额外的开销来帮助compliler处理范围等问题。 Here是一篇有解释的文章。我们谈论的开销非常小,几乎从不值得担心。