如果我有一个标记为 throw() 的方法,例如
void method() throw()
{
// do some stuff, call other functions
}
然而内部确实发生了异常,gcc 将终止应用程序(带有消息“在抛出 'xyz' 实例后调用终止”)。
有没有办法避免这种行为?
例如,用于忽略 throw() 内容或强制生成 eh_frame 的命令行开关。等等。
你试过GCC 手册吗?
-fno-enforce-eh-specs
不要在运行时生成代码来检查是否违反异常规范。此选项违反了 C++ 标准,但可能有助于减少生产构建中的代码大小,就像定义 `
NDEBUG
'。这不会授予用户代码违反异常规范抛出异常的权限;编译器仍会根据规范进行优化,因此抛出意外异常会导致运行时出现未定义的行为。
它不会强制生成 EH 帧,但它应该停止调用std::unexpected()
,因此可能对您的情况有用。
正如文档所说,“编译器仍然根据规范进行优化”,因此例如当调用可以内联到捕获站点时它没有帮助method()
,因为编译器假设不需要捕获,因为空异常规范说不会抛出异常,因此如果抛出异常,它不会被捕获。如果调用method()
不能内联到捕获站点,它似乎工作,异常离开method()
而不调用std::unexpected()
并且可以在堆栈的更高位置被捕获。
编辑:这仍然会调用std::terminate()
,即使-fno-enforce-eh-specs
:
void func() throw() { throw ""; }
void func2() { func(); }
int main() { try { func2(); } catch (...) { } }
编译器可以看到对的调用func2
只调用了一个无抛出函数,因此catch
永远不需要,因此被优化掉了。当异常被抛出时,它不会被捕获。
这确实适用-fno-enforce-eh-specs
并且不会终止:
/* func2.cc */
void func() throw();
void func2() { func(); }
/* main.cc */
void func2();
int main() { try { func2(); } catch (...) { } }
这里,在编译时main.cc
,编译器无法判断是否func2
要抛出异常,因为它没有异常规范,并且它的定义在 中不可见main.cc
,所以catch
不能省略。当抛出异常时,它将被捕获。
您可以通过调用 ... 来提供自己的终止处理程序,std::set_terminate
但是我认为从那里返回是不合法的,所以它唯一能做的就是以某种方式终止。
您可以提供自己的意外异常处理程序std::set_unexpected
:默认调用std::terminate
,但您可以做一些不同的事情(例如记录和吞下异常)。但是,您是否可以有效地恢复取决于您的程序。此外,我已经看到它被标记为已弃用,因此依赖它可能不是最好的主意。