Обработка компилятором / платформой ошибочных обработчиков std::terminate()

#c

#c

Вопрос:

Просматривая часть кода, я наткнулся на багги std::terminate() обработчик, который не завершал программу, но возвращался. Основываясь на документации для std::set_terminate() , я думаю, что это относится к области неопределенного — или, по крайней мере, определенного реализацией — поведения.

В Linux и при компиляции с использованием GCC я обнаружил, что ядра сбрасывались, что подразумевает, что какой-то ангел-хранитель вызывал abort () или что-то подобное от нашего имени.

Итак, я написал следующий тестовый фрагмент, который подтвердил мою догадку. Похоже, что GCC или его библиотека std переносят std::terminate() обработчики, поэтому они завершают программу.

 #include <iostream>
#include <exception>
#include <dlfcn.h>

// Compile using
// g   main.cpp -ldl

// Wrap abort() in my own implementation using
// dlsym(), so I can see if GCC generates code to
// call it if my std::terminate handler doesn't.
namespace std
{
    void abort()
    {
        typedef void (*aborter)();
        static aborter real_abort = 0x0;
        if (0x0 == real_abort)
        {
            void * handle = 0x0;
            handle = dlsym(RTLD_NEXT, "abort");
            if (handle)
            {
                real_abort = (aborter )(handle);
            }
        }
        std::cout << "2. Proof that GCC calls abort() if my buggyn"
                  << "   terminate handler returns instead of terminating."
                  << std::endl;
        if (real_abort)
        {
            real_abort();
        }
    }
}

// Buggy terminate handler that returns instead of terminating
// execution via abort (or exit)
void buggyTerminateHandler()
{
    std::cout << "1. In buggyTerminateHandler." << std::endl;
}

int main (int argc, char ** argv)
{
    // Set terminate handler
    std::set_terminate(buggyTerminateHandler);
    // Raise unhandled exception
    throw 1;
}
  

То, что компилятор (или библиотека) будет переносить std::terminate() обработчики, кажется разумным, поэтому, на мой взгляд, я бы предположил, что большинство компиляторов делают что-то в этом роде.

Кто-нибудь может посоветовать относительно поведения в Windows с использованием Visual Studio или OS X с использованием GCC?

Комментарии:

1. То же самое для MSCRT, он вызывает abort() при возврате terminate().

2. Если возвращается обработчик завершения, поведение не определено. Компиляторы обычно обрабатывают это путем вызова std::abort . Полагайтесь на это на свой собственный (очень реальный) риск.

3. Спасибо @HansPassant и n.m. Я не собирался использовать этот угловой случай — просто любопытно. Спасибо, что отметили поведение MSCRT.