关于在C++中安全使用catch(...)

Ste*_*and -2 c++ exception-handling exception catch-all

我和同事争论使用的危险性 catch(...)

他指的是一种可能的用法,严格暗示任何catch(...)后跟跟踪/日志:以帮助确定一些非托管异常的起源.

我个人对此持怀疑态度.你知道任何明确的安全使用吗?catch(...)

编辑:对于辩论中的那些人,我的同事刚刚在程序员网站上向我指出了这个问题.

Ste*_*sop 5

catch(...)我所知道的最清楚有趣的安全用途是卸载用于处理共享函数的各种异常的代码:

void handle_error() {
    try {
        throw;
    } catch (TiresomelyPedanticException &) {
        # lah lah I don't care
        return;
    } catch (InterestingException &) {
        log_something();
        throw;
    }
    // etc. This catch chain may *or may not* need a catch(...)
    // of its own, it depends whether part of its job is to
    // deal with the "miscellaneous" case.
}
Run Code Online (Sandbox Code Playgroud)

你使用这样的功能:

try {
    blah();
} catch(...) {
    handle_error();
}
Run Code Online (Sandbox Code Playgroud)

... 别的地方 ...

try {
    something_that_throws_the_same_exceptions_as_blah();
} catch (...) {
    handle_error();
}
Run Code Online (Sandbox Code Playgroud)

不过,上面的模式可能会变成C++ 03-ism.在C++ 11中,编写捕获lambda非常容易,以下内容可能对调用者更有用,并且catch(...)模式中没有:

template <typename Func>
auto do_and_handle_error(Func f) -> decltype(f()) {
    try {
        return f();
    } // catch chain goes here
}
Run Code Online (Sandbox Code Playgroud)

使用它像:

do_and_handle_error(blah);
Run Code Online (Sandbox Code Playgroud)

或者当blah拿出参数时实际上证明是必要的:

do_and_handle_error([&](void) { return blah(arg1,arg2); });
Run Code Online (Sandbox Code Playgroud)

无聊的用法catch(...)是保证在程序终止之前堆栈将被解除:

int my_main() {
    RAIIClass some_object_i_want_to_get_destroyed_no_matter_what;
    some_code_that_might_throw();
    return 0;
}

int main() {
    try {
        return my_main();
    } catch (...) {
        throw;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果没有catch,标准会将其指定为未指定或实现定义,some_object如果代码抛出则是否销毁.