std::set_terminate(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME πŸ’…

okay so welcome to std::set_terminate(3), bestie β€” this is the C++ Standard Libary manual page for std::set_terminate β€” std::set_terminate. It's giving main-character energy for your global terminate handler, fr fr. πŸ’–

✨ Synopsis ✨

Defined in header <exception>
std::terminate_handler set_terminate( std::terminate_handler f )
(until C++11)
throw();
std::terminate_handler set_terminate( std::terminate_handler f )
(since C++11)
noexcept;

Okay so here's the vibe: it makes f the new global terminate handler function and returns the previously installed std::terminate_handler. ✨

⚠️ bestie, f shall terminate execution of the program without returning to its caller β€” otherwise the behavior is undefined. No cap, do not return from it. πŸ’€

This function is thread-safe, and β€” since C++11 β€” every call to std::set_terminate synchronizes-with (see std::memory_order) subsequent calls to std::set_terminate and std::get_terminate. 🫢

πŸŽ€ Parameters πŸŽ€

  • f β€” pointer to function of type std::terminate_handler, or null pointer.

🌸 Return value 🌸

The previously-installed terminate handler, or a null pointer value if none was installed. Periodt. πŸ’…

πŸ”₯ Example πŸ”₯

// Run this code πŸ‘‡

#include <cstdlib>
#include <exception>
#include <iostream>

int main()
{
    std::set_terminate([]()
    {
        std::cout << "Unhandled exception\n" << std::flush;
        std::abort();
    });
    throw 1;
}

Possible output:

Unhandled exception
bash: line 7:  7743 Aborted                 (core dumped) ./a.out

The terminate handler will also work for launched threads, so it can be used as an alternative to wrapping the thread function with a try/catch block. In the following example, since the exception is unhandled, std::terminate will be called. 🧡✨

// Run this code πŸ‘‡

#include <iostream>
#include <thread>

void run()
{
    throw std::runtime_error("Thread failure");
}

int main()
{
    try
    {
        std::thread t{run};
        t.join();
        return EXIT_SUCCESS;
    }
    catch (const std::exception& exc)
    {
        std::cerr << "Exception: " << exc.what() << '\n';
    }
    catch (...)
    {
        std::cerr << "Unknown exception caught\n";
    }
    return EXIT_FAILURE;
}

Possible output:

terminate called after throwing an instance of 'std::runtime_error'
  what():  Thread failure
Aborted (core dumped)

With the introduction of the terminate handler, the exception thrown from the non-main thread can be analyzed, and exit can be gracefully performed. πŸ’–

// Run this code πŸ‘‡

#include <iostream>
#include <thread>

class foo
{
public:
    foo() { std::cerr << "foo::foo()\n"; }
    ~foo() { std::cerr << "foo::~foo()\n"; }
};

// Static object, expecting destructor on exit
foo f;

void run()
{
    throw std::runtime_error("Thread failure");
}

int main()
{
    std::set_terminate([]()
    {
        try
        {
            std::exception_ptr eptr{std::current_exception()};
            if (eptr)
            {
                std::rethrow_exception(eptr);
            }
            else
            {
                std::cerr << "Exiting without exception\n";
            }
        }
        catch (const std::exception& exc)
        {
            std::cerr << "Exception: " << exc.what() << '\n';
        }
        catch (...)
        {
            std::cerr << "Unknown exception caught\n";
        }
        std::exit(EXIT_FAILURE);
    });

    std::thread t{run};
    t.join();
}

Output:

foo::foo()
Exception: Thread failure
foo::~foo()

πŸ¦‹ See also πŸ¦‹

  • terminate β€” function called when exception handling fails (function)
  • get_terminate (C++11) β€” obtains the current terminate_handler (function)
  • terminate_handler β€” the type of the function called by std::terminate (typedef)

mwah πŸ’‹ sign-off: source http://cppreference.com, version/date 2024.06.10, page std::set_terminate(3). Stay iconic, bestie! πŸŒˆπŸ‘‘

πŸ“¦ where this page comes from