Under certain circumstances, terminating a function by throwing an exception will trigger undefined behavior. For instance, the C++ Standard, [basic.stc.dynamic.deallocation], paragraph 3 , states in part [ISO/IEC 14882-2014], states in part:
If a deallocation function terminates by throwing an exception, the behavior is undefined.
In these situations, the function should logically be declared noexcept
because throwing an exception from the function can never have well-defined behavior. The C++ Standard, [except.spec], paragraph 15, states [ISO/IEC 14882-2014]:
A deallocation function with no explicit exception-specification is treated as if it were specified with noexcept(true).
...
In this noncompliant code example, the class destructor does not meet the implicit noexcept
guarantee because it may throw an exception even if it was called as the result of an exception being thrown. Consequently, it is declared as noexcept(false)
but still can trigger undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdexcept> class S { bool shouldThrow() const; public: ~S() noexcept(false) { // Normal processing if (shouldThrow()) { throw std::logic_error("Something bad"); } } }; |
...
In this noncompliant code example, a global deallocation is declared noexcept(false)
and throws an exception if some conditions are not properly met. However, throwing from a deallocation function results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdexcept> bool performDealloc(void *); void operator delete(void *ptr) noexcept(false) { if (performDealloc(ptr)) { throw std::logic_error("Something bad"); } } |
...