The std::terminate and std::unexpected Functions

In C++, both std::terminate and std::unexpected are functions that handle critical errors and unexpected situations related to exceptions. They come into play when the exception-handling mechanism fails in specific ways, such as when an exception is not caught, or an unexpected type of exception is thrown.

std::terminate

std::terminate is called when the C++ runtime encounters a situation where normal exception handling cannot proceed. It is designed to abort program execution immediately, without unwinding the stack (i.e., without destructing local objects).

Situations where std::terminate is invoked include:

  • Uncaught exceptions: If an exception is thrown and not caught by any catch block, the program calls std::terminate by default.
  • Throwing an exception from a noexcept function: If a function marked as noexcept throws an exception, std::terminate is called.
  • Second exception during stack unwinding: If a second exception is thrown while the stack is unwinding due to a previous exception, the program terminates.

You can set your own custom handler for std::terminate by using std::set_terminate.

Example:

#include <iostream>
#include <exception>

void customTerminate() {
    std::cerr << "Custom terminate called! Exiting...\n";
    std::abort();
}

int main() {
    std::set_terminate(customTerminate);  // Setting a custom terminate handler
    throw 10;  // Will trigger std::terminate since there is no catch block
}

std::unexpected (Deprecated in C++11 and Removed in C++17)

std::unexpected was originally used to handle the case when a function throws an exception not listed in its exception specification. In pre-C++11 code, exception specifications (like throw(int)) were used to declare the types of exceptions a function could throw. If an unexpected type of exception was thrown, std::unexpected was invoked.

For example:

void func() throw(int) {  // Indicates func() can only throw int
    throw 20.5;  // Throws a double, leading to std::unexpected
}

However, this feature has been deprecated since C++11 and removed in C++17, as exception specifications were replaced with the more modern noexcept specifier. In modern C++, std::terminate will be invoked instead of std::unexpected.

Key Differences

  • std::terminate: Handles uncaught exceptions or exceptions thrown in noexcept functions and ensures immediate termination.
  • std::unexpected (deprecated): Handled unexpected exceptions thrown in functions with restrictive exception specifications, but this mechanism is obsolete in modern C++.

In modern C++ development, std::terminate is more relevant, while std::unexpected has been phased out. Understanding std::terminate is important for handling critical program failures and ensuring that your program terminates safely in scenarios where exception handling cannot proceed.