Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The std::abort() and std::_Exit() functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit(), and without executing destructors for objects with automatic, thread, or static storage duration. It is implementation-defined as to whether open Whether open streams with unwritten buffered data are flushed, open streams are closed, or temporary files are removed [ISO/IEC 9899:1999] is implementation defined. Because these functions can leave external resources in an indeterminate state, they should only be called explicitly only in direct response to a critical error in the application.

...

The C++ Standard defines several ways in which std::terminate() may be called implicitly by an implementation [ISO/IEC 14882-2014]:

  • When the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception, calls a function that exits via an exception. ([except.throw], paragraph 7)
  • When a throw-expression with no operand attempts to rethrow an exception and no exception is being handled. ([except.throw], paragraph 9)
  • When the exception handling mechanism cannot find a handler for a thrown exception. ([except.handle], paragraph 9)
  • When the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception. ([except.spec], paragraph 9)
  • When the destruction of an object during stack unwinding terminates by throwing an exception. ([except.ctor], paragraph 3)
  • When initialization of a non-local nonlocal variable with static or thread storage duration exits via an exception. ([basic.start.init], paragraph 6)
  • When destruction of an object with static or thread storage duration exits via an exception. ([basic.start.term], paragraph 1)
  • When execution of a function registered with std::atexit() or std::at_quick_exit() exits via an exception. ([support.start.term], paragraphs 8 and 12)
  • When the implementation’s default unexpected exception handler is called. ([except.unexpected], paragraph 2) Note that std::unexpected() is currently deprecated.
  • When std::unexpected() throws an exception which that is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception() is not included in that dynamic-exception-specification. ([except.unexpected], paragraph 3)
  • When the function std::nested_exception::rethrow_nested() is called for an object that has captured no exception. ([except.nested], paragraph 4)
  • When execution of the initial function of a thread exits via an exception. ([thread.thread.constr], paragraph 5)
  • When the destructor is invoked on an object of type std::thread that refers to a joinable thread. ([thread.thread.destr], paragraph 1)
  • When the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread. ([thread.thread.assign], paragraph 1)
  • When calling condition_variable::wait()condition_variable::wait_until(), or condition_variable::wait_for() results in a failure to meet the post-conditionpostconditionlock.owns_lock() == true or lock.mutex() is not locked by the calling thread. ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)
  • When calling condition_variable_any::wait()condition_variable_any::wait_until(), or condition_variable_any::wait_for() results in a failure to meet the post-conditionpostconditionlock is not locked by the calling thread. ([thread.condition.condvarany], paragraphs 11, 16, and 22)

In many circumstances, the call stack will not be unwound in response to the implicit call to std::terminate(), and in a few cases, it is implementation-defined as to whether or not stack unwinding will occur or not. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], states, in part:

...

Do not explicitly or implicitly call std::abort() or std::_Exit(). When the default terminate_handler is installed , or the current terminate_handler responds by calling std::abort() or std::_Exit(), do not explicitly or implicitly call std::terminate(). Abnormal process termination is the typical vector for denial-of-service  attacksattacks.

Noncompliant Code Example

...

In this compliant solution, f() handles all exceptions thrown by throwing_func(), and does not rethrow:

Code Block
bgColor#ccccff
langcpp
#include <cstdlib>

void throwing_func() noexcept(false);

void f() {
  try {
    throwing_func();
  } catch (...) {
    // Handle error
  }
}

int main() {
  if (0 != std::atexit(f)) {
    // Handle error
  }
  // ...
}

...

ERR30-CPP-EX1: It is acceptable, after indicating the nature of the problem to the operator, to explicitly call std::abort()std::_Exit(), or std::terminate() in response to a critical program error for which no recovery is possible, after indicating the nature of the problem to the operator, as in this example:

Code Block
bgColor#ccccff
langcpp
#include <exception>

void report(const char *msg) noexcept;
[[noreturn]] void fast_fail(const char *msg) {
  // Report error message to operator.
  report(msg);
 
  // Terminate
  std::terminate();
}
 
void critical_function_that_fails() noexcept(false);
 
void f() {
  try {
    critical_function_that_fails();
  } catch (...) {
    fast_fail("Critical function failure");
  }
}

Note that the assert() macro is permissible under this exception , as because failed assertions will notify the operator on the standard error stream in an implementation-defined manner prior to before calling std::abort().

Risk Assessment

Allowing the application to abnormally terminate can lead to resources not being freed, closed, etc. It is frequently a vector for denial-of-service attacks.

...