0

如果我有一个标记为 throw() 的方法,例如

 void method() throw()
 {
      // do some stuff, call other functions
 }

然而内部确实发生了异常,gcc 将终止应用程序(带有消息“在抛出 'xyz' 实例后调用终止”)。

有没有办法避免这种行为?

例如,用于忽略 throw() 内容或强制生成 eh_frame 的命令行开关。等等。

4

2 回答 2

2

你试过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不能省略。当抛出异常时,它将被捕获。

于 2012-10-26T13:36:50.440 回答
1

您可以通过调用 ... 来提供自己的终止处理程序,std::set_terminate但是我认为从那里返回是不合法的,所以它唯一能做的就是以某种方式终止。

您可以提供自己的意外异常处理程序std::set_unexpected:默认调用std::terminate,但您可以做一些不同的事情(例如记录和吞下异常)。但是,您是否可以有效地恢复取决于您的程序。此外,我已经看到它被标记为已弃用,因此依赖它可能不是最好的主意。

于 2012-10-26T12:32:15.403 回答