【问题标题】:Compiler warning or Static Analysis for violating noexcept guarantee? [duplicate]违反 noexcept 保证的编译器警告或静态分析? [复制]
【发布时间】:2019-03-24 12:13:52
【问题描述】:

我大量使用 noexcept,不幸的是,如果某些传递依赖最终在极少数情况下抛出(我们不知道),崩溃非常难以调试 - 因为 noexcept 导致 std::terminate 被调用。

有没有办法在编译时检测这些违规行为?在下面的例子中 问题很明显,但默认情况下没有编译器捕获它。我意识到这并非在所有情况下都是可能的,但更简单的情况肯定是可能的

#include <stdexcept>

void baz()
{
    throw std::runtime_error("std::terminate awaits");
}

void bar()
{
    baz();
}

void foo() noexcept
{
    bar();
}

神螺栓链接:https://godbolt.org/z/Ooet58

是否有我不知道的编译器标志?捕捉到这一点的静态分析工具怎么样?

【问题讨论】:

  • 为此分析深层函数调用似乎很棘手。关于简单地使用 noexcept(false) 函数的警告似乎太烦人了。
  • 我学会了忽略noexcept 标签,除非我确定我的例程不能抛出。这通常意味着我只标记不调用任何东西的叶子函数。话虽这么说,运算符重载滑入了一个我没有注意到的难以发现的函数调用……你好 std::terminate。叹息
  • 我同意“除非你肯定知道,否则不要标记”,但代码会更改。曾经是叶函数的东西被其他人重构,这会调用另一个抛出的函数。或者,您在 noexcept 函数中调用用户提供的回调(例如,您正在编写一个事件循环),然后抛出
  • 调试难度如何?注册您自己的终止处理程序并在那里放置一个断点。或者,如果您正在运行无法直接调试的守护进程,请打印堆栈跟踪,甚至更好:创建可以在本地调试的核心转储。
  • 在单个编译单元中,这可能很容易处理,尽管我不知道有什么工具可以做到这一点。但从哲学上讲,从共享/动态库调用函数时应该如何检测到这一点?

标签: c++ c++11 noexcept


【解决方案1】:

查看微软的静态分析工具,它可以准确地检查出这种违规行为:Don’t throw in noexcept

编辑:该工具还可以告诉您哪些函数可以标记为 noexcept,这应该可以更容易地显着缩小抛出函数的范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2011-06-24
    相关资源
    最近更新 更多