15

我正在尝试编写异常安全代码。我发现使用 C++11 的 noexcept 说明符使这个目标更容易实现。

当然,一般的想法是,一个函数应该被标记为“noexcept”,当且仅当它调用的所有函数也被标记为“noexcept”。

问题在于,在大型代码库中,来自不同人的补丁经常合并在一起,很难确保保持这种一致性。

因此,我希望能够运行静态分析,该分析可以列出标记为“nothrow”的函数调用未标记为“nothrow”的函数的所有位置。

据我在手册页中看到的,GCC 无法帮助我。有没有可以帮助我的独立工具?或者也许是其他一些编译器?

4

2 回答 2

6

如果您通过使用程序的 ABT 来避免指向函数的指针(并认为它们不安全),这当然是可能的。Clang 的 AST 是(尽管它的名字)这样的 ABT:您将看到函数的声明和定义。通过一次做一个定义,你已经有了一个很好的基线。

另一方面,我想知道这是否实用。看,问题是任何执行内存分配的函数都(自愿地)标记为可能抛出(因为new从不返回 null,而是抛出bad_alloc)。因此,noexcept在大多数情况下,您将仅限于少数功能。

当然还有像@GManNickG 这样的所有动态条件暴露,例如:

void foo(boost::optional<T> const t&) {
    if (not t) { return; }

    t->bar();
}

即使T::baris noexcept,取消引用 anoptional<T>可能会抛出(如果什么都没有)。当然,这忽略了我们已经排除了这个事实(这里)。

如果没有明确的条件说明函数何时可能throwstatic分析可能会被证明是……无用的。语言习语的设计考虑到了例外情况。


注意:作为题外话,可以重写可选类,以免暴露解引用,因此noexcept(如果回调是):

template <typename T>
class maybe {
public:

    template <typename OnNone, typename OnJust>
    void act(OnNone&& n, OnJust&& j) noexcept(noexcept(n()) and 
                                              noexcept(j(std::declval<T&>())))
    {
        if (not _assigned) { n(); return; }
        j(*reinterpret_cast<T*>(&_storage));
    }

private:
    std::aligned_storage<sizeof(T), alignof(T)>::type _storage;
    bool _assigned;
};

// No idea if this way of expressing the noexcept dependency is actually correct.
于 2013-02-01T18:38:30.233 回答
0

clang-tidy 检查 bugprone-exception-escape 试图找到可能直接或间接抛出异常的函数,而这些函数不应该抛出异常。这包括检查标有throw()或的功能noexcept

https://clang.llvm.org/extra/clang-tidy/checks/bugprone-exception-escape.html

于 2021-11-03T19:45:48.963 回答