Rule A15-5-3 (required, implementation, automated)

The std::terminate() function shall not be called implicitly.

Rationale

It is implementation-defined whether the call stack is unwound before std::terminate() is called. There is no guarantee that the destructors of automatic thread or static storage duration objects will be called. These are following ways to call std::terminate() function implicitly, according to (std::terminate() in CppReference [16]): an exception is thrown and not caught (it is implementation-defined whether any stack unwinding is done in this case) an exception is thrown during exception handling (e.g. from a destructor of some local object, or from a function that had to be called during exception handling)

the constructor or the destructor of a static or thread-local object throws an exception a function registered with std::atexit or std::at_quick_exit throws an exception

a noexcept specification is violated (it is implementation-defined whether any stack unwinding is done in this case) a dynamic exception specification is violated and the default handler for std::unexpected is executed a non-default handler for std::unexpected throws an exception that violates the previously violated dynamic exception specification, if the specification does not include std::bad_exception std::nested_exception::rethrow_nested is called for an object that isn’t holding a captured exception an exception is thrown from the initial function of std::thread a joinable std::thread is destroyed or assigned to Note: std::terminate_handler shall not be used.

Example

//% $Id: A15-5-3.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#include <stdexcept>
#include <thread>
extern bool F1();
class A
{
public:
A() noexcept(false)
{
// ...
throw std::runtime_error("Error1");
}
~A()
{
// ...
throw std::runtime_error("Error2"); // Non-compliant - std::terminate()
// called on throwing an exception
// from noexcept(true) destructor
}
};
class B
{
public:
~B() noexcept(false)
{
// ...
throw std::runtime_error("Error3");
}
};
void F2()
{
throw;

}
void ThreadFunc()
{
A a; // Throws an exception from a’s constructor and does not handle it in
// thread_func()
}
void F3()
{
try
{
std::thread t(&ThreadFunc); // Non-compliant - std::terminate() called
// on throwing an exception from
// thread_func()

if (F1())
{
throw std::logic_error("Error4");

}

else
{
F2(); // Non-compliant - std::terminate()
// active exception to be re-thrown

called if there is no
by f2

}
}
catch (...)
{
B b; // Non-compliant - std::terminate() called on throwing an
// exception from b’s destructor during exception handling

// ...
F2();
}
}
static A a; // Non-compliant - std::terminate() called on throwing an exception
// during program’s start-up phase
int main(int, char**)

{
F3(); // Non-compliant - std::terminate() called if std::logic_error is
// thrown
return 0;
}

See also

MISRA C++ 2008 [7]: 15-5-3 (Required) The terminate() function shall not be called implicitly.