在C回调中尝试{} catch(...){} - 糟糕的主意?

nne*_*neo 12 c++ exception-handling callback

我正在用C++实现回调,它将从普通的C代码中调用.我的main()函数已经是C++,但C代码将负责创建最终调用我的回调的线程.

现在我的回调看起来像

int handle_foo(void *userdata) {
    try {
        MyCPPClass *obj = static_cast<MyCPPClass *>(userdata);
        obj->doStuff();
        return 0; // no error
    } catch(...) {
        LogError("doStuff failed"); 
        return -1; // error
    }
}
Run Code Online (Sandbox Code Playgroud)

这个工作正常,但对我来说似乎很奇怪.此外,我失去了一些有用的功能,如找出的能力是什么被抛出(无需增加额外的巨额catch语句彼此,我的回调中的每一个).

这是try {} catch(...) {}合理的,还是有更好的方法来编写我的C回调?

sha*_*oth 7

是的,您必须捕获异常并希望将它们转换为有用的东西.让异常通过C代码传播会导致未定义的行为.充其量你不能指望C代码保持一致的程序状态.

有关简单示例,请参阅此答案.一个更难的例子是使用一些复杂的软件,例如SQLite - C代码将获取一些互斥量并且不会释放它,因为异常只是"飞过"而你的程序现在是吐司.

如果所有代码都是针对相同的C++运行时构建的,那么这也有可能"工作".如果您碰巧在Visual C++ 9中实现了回调,并且其他代码在Visual C++ 10中编写或者这些部分是针对静态运行时库编译的 - 您现在有两个不同的运行时,并且回调中的未处理异常会导致terminate()被调用.