编译不应抛出但仍然可以执行的函数的时间检测(noexcept或替代方法)

时间:2015-08-17 13:52:15

标签: c++ exception-handling

我知道noexcept只是提供信息,而gcc / clang不会触发此代码段的任何警告/错误:

void foo() noexcept
{
  throw 1;
}

int main()
{
  foo();
  return 0;
}

那么 - 是否存在一种方法或技术来标记函数不抛出任何东西,如果实现抛出,实际上会从编译器获得编译时警告/错误?

一个简单的用例 - 我有一个框架,它公开了客户端插件应该实现的一组接口,然后框架从共享对象加载插件,通过工厂实例化接口并调用接口方法。我希望在调用期间不会在库边界上抛出任何异常,因此我想将插件实现的接口中的所有函数标记为不抛出,而不是依赖于具有try / {{1}的实现阻止内部。有没有相关的常用技术/替代解决方案?

我也明白,没有编译时间检查可以检测到由于数据无效而在运行时可能发生的潜在结构化异常,但是有什么东西适用于至少C ++异常吗?

修改

感谢Jason的评论,我检查了函数指针发生了什么,并且还放了一点 - 至少在下面的片段中抱怨,gcc没有:

catch

1 个答案:

答案 0 :(得分:5)

请记住,noexcept是编译器的一个线索,它不需要提供机制来正确地展开此特定函数中的堆栈帧(以防止异常),从而允许它进行更多优化。如果抛出异常,可能无法正常恢复。

std :: move_if_noexcept 是noexcept目的的关键。对于具有移动语义的特定情况,需要使用noexcept,其描述为here

并且像你指出的那样,在编译时无法确定无效数据。并且在检测' throw'在函数的根范围内将是微不足道的,分析可能从该函数调用的所有可能的代码路径,以确定是否抛出异常是更多的工作。我怀疑所有的编译器都在他们的列表中有这个,并且正在努力寻求解决方案,但是noexcept从来就不是一个保证,所以我怀疑这是一个充满激情的辩论。

目前,您可能希望使用noexcept修饰函数,并允许编译器生成更快的代码,并且非常强烈地沟通抛出异常会产生不稳定的行为。但是,即使没有noexcept,编译器也可以执行其中一些优化。例如,编译器可以很容易地确定许多内联函数是合适的候选函数。

修改 正如@Creris正确指出的那样,如果找不到匹配的异常处理程序(这是非常不合适的),将立即调用std :: terminate(),但这肯定不会阻止开发人员在这些情况下使用throw。