Pergunta

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.

  1. Should noexcept be considered a safety guarantee, that the function when called will not only not throw but will not corrupt state?
  2. 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;
}

Working example of noexcept

Foi útil?

Solução

  1. 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. ;-)]
  2. Mu. A function shouldn't bother throwing if it expects to throw through a noexcept; it should just call std::terminate (or std::abort) instead.

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top