跳转至

异常处理

C 错误处理机制

  • 终止程序:如 assert

  • 返回错误码:需要自己找错误出在哪里,而且很多系统接口都会把错误码放到 errno 中。

实际中 C 程序都是使用错误码的方式处理错误,部分情况下使用终止程序处理严重的错误。

C++ 异常处理机制

当一个函数出现自己无法处理的错误时就可以抛出异常,让函数的直接或间接调用者处理这个问题。

try
{
    // 可能抛出异常的语句
}
catch(exceptionType variable)
{
    // 处理异常的语句
}

发生异常时必须将异常明确地抛出,try才能检测到;如果不抛出来,即使有异常try也检测不到。异常一旦抛出,会立刻被try检测到,并且不会再执行异常点(异常发生位置)后面的语句。意思就是:检测到异常后程序的执行流会发生跳转,从异常点跳转到catch所在的位置,位于异常点之后的、并且在当前try块内的语句就都不会再执行;即使catch语句成功地处理了错误,程序的执行流也不会再回退到异常点,所以这些语句永远都没有执行的机会。执行完 catch 块所包含的代码后,程序会继续执行 catch 块后面的代码。

因为异常会导致执行流跳转,程序中应尽量避免使用异常,频繁的异常抛出很容易引起不必要的错误。对于正常的返回值,或者不太严重、可以重试 / 恢复的错误,建议不使用异常,把它们归到正常的流程里。

几个使用异常的判断准则:

  • 不允许被忽略的错误;

  • 极少数情况下才会发生的错误;

  • 严重影响正常流程,很难恢复到正常状态的错误;

  • 无法本地处理,必须“穿透”调用栈,传递到上层才能被处理的错误。

noexcept

C++ 11提出了一个新的编译阶段命令:noexcept, 被它修饰的函数,就是告诉编译器这个函数不会抛出异常,允许编译器对该函数进行优化,不去加那些栈展开的额外代码,消除异常处理的成本。但承诺只是承诺,被修饰的函数如果真的抛出也不会报错。