如果我有一个标记为throw()的方法,例如
void method() throw()
{
// do some stuff, call other functions
}
然而异常发生在里面发生,gcc将终止应用程序(消息“在抛出'xyz'实例后调用终止”)。
有没有办法避免这种行为?
例如,命令行开关忽略throw()内容或强制生成eh_frame。等
答案 0 :(得分:2)
您是否尝试过GCC manual?
-fno-enforce-eh-specs
不要生成代码以在运行时检查是否违反了异常规范。此选项违反了C ++标准,但可能对减少生产版本中的代码大小很有用,就像定义“
NDEBUG
”一样。这不会为用户代码授予违反异常规范而抛出异常的权限;编译器仍然会根据规范进行优化,因此抛出意外异常会导致运行时出现未定义的行为。
它不强制生成EH帧,但它应该停止对std::unexpected()
的调用,因此可能对您的情况有用。
正如文档所说,“编译器仍然根据规范进行优化”,例如当对method()
的调用可以内联到catch站点时,它没有帮助,因为编译器假定不需要catch,因为空的异常规范说没有异常将被抛出,因此如果异常是抛出它不会被抓住。如果对method()
的调用无法进入catch网站,它似乎可以正常工作,异常会在不调用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
不能省略。抛出异常时会被捕获。
答案 1 :(得分:1)
您可以通过调用std::set_terminate
来提供自己的终止处理程序...但是我不认为从那里返回是合法的,所以它唯一能做的就是以某种方式终止。
您可以使用std::set_unexpected
提供自己的意外异常处理程序:默认情况下调用std::terminate
,但您可以执行不同的操作(例如记录和吞咽异常)。您是否可以有效恢复取决于您的计划。此外,我已经看到它被标记为已弃用,所以依靠这可能不是最好的主意。