- Yes. A function should not corrupt state, period, whether it throws or not. The fact that it might have wanted to throw an exception is immaterial. [Of course, there's no guarantee that it won't crash the program. That sort of behavior should probably be documented, though. ;-)]
- Mu. A function shouldn't bother throwing if it expects to throw through a
noexcept
; it should just callstd::terminate
(orstd::abort
) instead.
noexcept and reliability guarantees
-
12-10-2022 - |
سؤال
Recently I tried to answer what I thought would be a simple question on the noexcept
exception specification. The end result being that I found that my fundamental understanding of noexcept
was wrong.
While reading the current draft standard to correct my misunderstanding, I found myself asking a few questions about noexcept
that weren't answered here.
- Should
noexcept
be considered a safety guarantee, that the function when called will not only not throw but will not corrupt state? - Assuming that (1.) is false: Is it correct to use
noexcept
as a portable FailFast to terminate the application without cleanup to prevent corruption of saved state?
Clarification to (2.): The intent is ONLY to prevent destructor calls further up the stack from the noexcept
not to prevent unwinding within it. This is based on the assumption that this is a perfect RAII environment and the destructors up the stack could flush out global state to persistence thus corrupting it.
Example of how unwinding is not preformed:
#include <iostream>
#include <exception>
namespace{
struct foo{
void change_state() noexcept
{
// change state and fail
throw std::exception();
}
~foo(){
std::cout << "Destructor called, saved state corrupted!" <<std::endl;
}
};
}
int main(){
::std::set_terminate([](){
std::cout<< "Terminate called" <<std::endl;
});
foo f;
f.change_state();
return 0;
}
المحلول
نصائح أخرى
noexcept
is a contractual guarantee, much like an assert
which can't be turned off. If a function marked noexcept
tries to exit via an exception, a post-condition has been
violated, and you can't count on anything; the program will be
terminated. Thus, 1 is false.
With regards to 2, it is more difficult. The implementation may
unwind the stack up until it tries to leave the function with
the noexcept
; it's not 100% clear (at least to me) that it may
not unwind the stack further. If I want to terminate the
application without cleanup, then I'll call abort()
, which is
guaranteed to exit immediately without any further actions. It
also tells the reader exactly what is happening, rather than
counting on some secondary effect of a different feature.