#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.