The std::abort()
, std::quick_exit()
, 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. How a system manages open streams when a program ends is implementation-defined [ISO/IEC 9899:1999]. Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (See ERR50-CPP-EX1 for more information.)
The std::terminate()
function calls the current terminate_handler
function, which defaults to calling std::abort()
.
The C++ Standard defines several ways in which std::terminate()
may be called implicitly by an implementation [ISO/IEC 14882-2014]:
std::atexit()
or std::at_quick_exit()
exits via an exception ([support.start.term], paragraphs 8 and 12)std::unexpected()
is currently deprecated.std::unexpected()
throws an exception 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)std::nested_exception::rethrow_nested()
is called for an object that has captured no exception ([except.nested], paragraph 4)std::thread
that refers to a joinable thread ([thread.thread.destr], paragraph 1)std::thread
that refers to a joinable thread ([thread.thread.assign], paragraph 1)condition_variable::wait()
, condition_variable::wait_until()
, or condition_variable::wait_for()
results in a failure to meet the postcondition: lock.owns_lock() == true
or lock.mutex()
is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)condition_variable_any::wait()
, condition_variable_any::wait_until()
, or condition_variable_any::wait_for()
results in a failure to meet the postcondition: lock
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 an implicit call to std::terminate()
, and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:
In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before
std::terminate()
is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all beforestd::terminate()
is called. In all other situations, the stack shall not be unwound beforestd::terminate()
is called.
Do not explicitly or implicitly call std::quick_exit()
, 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 attacks.
It is acceptable to call a termination function that safely executes destructors and properly cleans up resources, such as std::exit()
.
Noncompliant Code Example
In this noncompliant code example, the call to f()
, which was registered as an exit handler with std::at_exit()
, may result in a call to std::terminate()
because throwing_func()
may throw an exception.
#include <cstdlib> void throwing_func() noexcept(false); void f() { // Not invoked by the program except as an exit handler. throwing_func(); } int main() { if (0 != std::atexit(f)) { // Handle error } // ... } |
In this compliant solution, f()
handles all exceptions thrown by throwing_func()
and does not rethrow.
#include <cstdlib> void throwing_func() noexcept(false); void f() { // Not invoked by the program except as an exit handler. try { throwing_func(); } catch (...) { // Handle error } } int main() { if (0 != std::atexit(f)) { // Handle error } // ... } |
ERR50-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, as in this example.
#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"); } } |
The assert()
macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an implementation-defined manner before calling std::abort()
.
Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR50-CPP | Low | Probable | Medium | P4 | L3 |
Tool | Version | Checker | Description |
---|---|---|---|
Astrée | stdlib-use | Partially checked | |
CodeSonar | BADFUNC.ABORT | Use of abort | |
Helix QAC | C++5014 | ||
Klocwork | |||
LDRA tool suite | 122 S | Enhanced Enforcement | |
Parasoft C/C++test | CERT_CPP-ERR50-a | The execution of a function registered with 'std::atexit()' or 'std::at_quick_exit()' should not exit via an exception | |
Polyspace Bug Finder | CERT C++: ERR50-CPP | Checks for implicit call to terminate() function (rule partially covered) | |
PRQA QA-C++ | 5014 | ||
PVS-Studio | V667 | ||
RuleChecker | stdlib-use | Partially checked | |
SonarQube C/C++ Plugin | S990 |
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
SEI CERT C++ Coding Standard | ERR51-CPP. Handle all exceptions |
MITRE CWE | CWE-754, Improper Check for Unusual or Exceptional Conditions |
[ISO/IEC 9899-2011] | Subclause 7.20.4.1, "The abort Function"Subclause 7.20.4.4, "The _Exit Function" |
[ISO/IEC 14882-2014] | Subclause 15.5.1, "The |
[MISRA 2008] | Rule 15-3-2 (Advisory) Rule 15-3-4 (Required) |