问题
I'm trying to write exception safe code. I find that using C++11's noexcept specifier makes this goal a whole lot more achievable.
The general idea, of course, is that a function should be marked as 'noexcept' if, and only if all the functions that it calls are also marked as 'noexcept'.
The problem is that in a large code base, where patches from different people are often merged together, it is hard to ensure that this consistency is maintained.
So I would like to be able to run a static analysis that could list all places where a function that is marked 'nothrow' calls a function that is not marked as 'nothrow'.
As far as I can see in the man-page, GCC cannot help me here. Are there any stand-alone tools that can help me? Or maybe some other compilers?
回答1:
It certainly seems possible if you avoid pointer to functions (and deem them unsafe) by using the ABT of the program. Clang's AST is (despite its name) such an ABT: you will see both declarations and definitions of the functions. By doing your work one definition at a time, you will already have a good baseline.
On the other hand, I wonder whether this is practical. See, the problem is that any function performing a memory allocation is (voluntarily) marked as potentially throwing (because new
never returns null, but throws bad_alloc
instead). Therefore, your noexcept
will be limited to a handful of functions in most cases.
And of course there are all the dynamic conditions like @GManNickG exposed, for example:
void foo(boost::optional<T> const t&) {
if (not t) { return; }
t->bar();
}
Even if T::bar
is noexcept
, dereferencing an optional<T>
may throw (if there is nothing). Of course, this ignores the fact that we already ruled this out (here).
Without having clear conditions on when a function might throw
, static
analysis might prove... useless. The language idioms are designed with exceptions in mind.
Note: as a digression, the optional class could be rewritten so as not to exposed dereferencing, and thus be noexcept
(if the callbacks are):
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.
来源:https://stackoverflow.com/questions/14652188/static-analysis-of-noexcept-violations-in-c