#include <iostream>
#include <stdexcept>
class Test {
public:
Test() { std::cout << "Constructor called" << std::endl; }
~Test() { std::cout << "Destructor called" << std::endl; }
};
int main() {
Test obj1;
try
{
Test obj2;
throw std::runtime_error("Exception thrown");
} // Object 2 is destroyed here
catch (...)
{
throw; // std::abort
}
} // not reached (implementation defined), Object 1 destructor never called
Я понимаю, почему деструктор obj2
не вызывается, поскольку его реализация определена, если раскручивание стека происходит в случае неперехваченного исключения, но я не понимаю, почему на обычных платформах Linux это разрешено или думает, что оно должно завершиться с помощью SIGSEGV сигнал. Насколько я понимаю, следует ожидать SIGABRT.
[кроме.handle] «Если соответствующий обработчик не найден, вызывается функция std::terminate();» Судя по твоему богу, std::terminate
действительно назывался. Стандарт, кажется, не определяет, что должно произойти дальше, поэтому я думаю, что убийство SIGSEGV допустимо. Вы можете получить такое же поведение, просто вызвав прекращение.
Вы можете получить такое же поведение, если ваша программа просто вызывает std::abort()
. Стандарт C++ гласит: «Вызывает ненормальное завершение программы», но не указывает, что это должен быть сигнал SIGABRT. std::abort
регулируется POSIX, в котором говорится, что он должен генерировать сигнал SIGABRT. pubs.opengroup.org/onlinepubs/9699919799/functions/abort.html
Существует по крайней мере заголовок <csignal>, определяющий сигналы, и cppref.com немного неясно, требует ли только POSIX или cpp lang в целом std::abort использовать SIGABRT en.cppreference.com/w/cpp/utility/ программа/SIG_types
Это артефакт (/ошибка?) Compiler Explorer. SIGABRT
становится SIGSEGV
: https://github.com/compiler-explorer/compiler-explorer/issues/5224
Запуск на моем компьютере дает:
$ ./example ; echo "Program returned: $?"
Constructor called
Constructor called
Destructor called
terminate called after throwing an instance of 'std::runtime_error'
what(): Exception thrown
Aborted
Program returned: 134
Даже в Compiler Explorer вы можете обработать SIGABRT
, чтобы увидеть, что он все еще там, после него есть только SIGSEGV
: https://godbolt.org/z/6dYsP5K5K
std::signal(SIGABRT, [](int) {
std::cout << "Caught SIGABRT\n" << std::flush;
});
std::signal(SIGSEGV, [](int) {
std::cout << "Caught SIGSEGV\n" << std::flush;
std::_Exit(1);
});
Вывод компилятора:
Program returned: 1
terminate called after throwing an instance of 'std::runtime_error'
what(): Exception thrown
Constructor called
Constructor called
Destructor called
Caught SIGABRT
Caught SIGSEGV
Мой компьютер:
$ ./example ; echo "Program returned: $?"
Constructor called
Constructor called
Destructor called
terminate called after throwing an instance of 'std::runtime_error'
what(): Exception thrown
Caught SIGABRT
Aborted
Program returned: 134
Это то, что я получаю за один раз, не выполняя сначала это на своей машине™ :-)
@n.m.couldbeanAI Разве это не нарушает стандарт CPP?