编译时检测不应该抛出但仍然抛出的函数(没有except或替代方法)
Compile time detection of functions that should not throw but still do (noexcept or alternative ways)
我知道noexcept只是提供信息,gcc/clang不会触发任何警告/错误:
void foo() noexcept
{
throw 1;
}
int main()
{
foo();
return 0;
}
所以-有没有一种方法或技术来标记一个函数不抛出任何东西,实际上得到编译时的警告/错误从编译器,如果实现抛出?
一个简单的用例——我有一个框架,它公开了一组客户端插件应该实现的接口,然后框架从共享对象加载插件,通过工厂实例化接口并调用接口方法。我希望在调用期间没有异常抛出库边界,所以我想标记由插件实现的接口中的所有函数不抛出,而不是依赖于具有try
/catch
块内部的实现。有什么常见的技术/替代解决方案吗?
我也明白,没有编译时检查可以检测到由于无效数据在运行时可能发生的潜在结构化异常,但至少有c++异常工作吗?
编辑
感谢Jason的评论,我检查了函数指针发生了什么,也让我失望了一点——clang至少抱怨了下面的代码片段,gcc没有:
void foo() noexcept
{
throw 1;
}
void bar() noexcept(false)
{
}
int main()
{
void (*safe_function_one)() noexcept = &foo;
void (*safe_function_two)() noexcept = &bar;
return 0;
}
请记住,noexcept是向编译器提示,它不需要提供在这个特定函数中适当展开堆栈帧的机制(以防止出现异常),从而允许它进行更多的优化。如果抛出异常,则可能无法进行适当的恢复。
std::move_if_noexcept是noexcept的关键。对于使用move语义的特定情况,Noexcept是必需的,这里有描述。
正如您指出的那样,在编译时无法确定无效数据。虽然在函数的根作用域中检测'throw'是微不足道的,但分析可能从该函数调用的所有可能的代码路径以确定是否抛出异常则需要更多的工作。我怀疑所有的编译器都有这个问题,并且都在努力寻找解决方案,但是noexcept从来都不是保证,所以我怀疑这是一个相当有激情的争论。
现在,您可能希望用noexcept修饰函数,并允许编译器生成更快的代码,并且非常强烈地告知抛出异常将产生不稳定的行为。然而,编译器无论如何都可以执行其中的一些优化,即使没有noexcept。例如,编译器可以很容易地确定许多内联函数是很好的候选函数。
编辑:正如@Creris正确指出的那样,如果无法找到匹配的异常处理程序(这是非常不希望的),std::terminate()将被立即调用,但这当然不会阻止开发人员在这些情况下使用throw。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 如果没有malloc,链表实现将失败
- 数组索引的值没有增加
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 变量没有改变?通过向量的函数调用
- 没有名称的C++模板参数
- 在线编译器中的分段C++没有打印消息
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 没有用于初始化C++中的变量模板的匹配构造函数
- 调用'begin(int [n])'没有匹配函数
- 使用C++程序合并排序没有得到正确的输出
- 为什么在这个代码结束循环中没有得到结束
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 用MacOS Mojave编译C++:致命错误:mpi.h:没有这样的文件或目录
- 编译时检测不应该抛出但仍然抛出的函数(没有except或替代方法)