Что происходит, когда заканчиваются функции f () и g ()?
#include<iostream>
using namespace std;
class A
{
~A(){}
}
void f()
{
cout << "terminate" << endl;
}
void g()
{
cout << "unexpected" << endl;
}int main()
{
set_terminate(f);
set_unexpected(g);
throw 5;
cout << "end" << endl;
return 0;
}
Почему вызывается функция abort ()?
А когда называется деструктор? Я не могу найти логику: ((((((((
Соответствующие правила четко определены в стандарте. Есть ряд правил, которые просто произносятся и применяются к вашему примеру:
throw
без catch
результаты в вызове terminate
или функция, установленная для этого. unexpected
или функция, установленная для этого.15.1 Бросок исключения
Параграф 8:
Если в настоящее время не обрабатывается ни одно исключение, выполняется выражение throw без вызовов операндов
прекратить () (15.5.1).
15.4 Спецификации исключений
Параграф 8:
Всякий раз, когда выдается исключение, и при поиске обработчика (15.3) встречается самый внешний блок
функция со спецификацией исключений, функция неожиданно () вызывается (15.5.2), если спецификация исключений
не допускает исключения
Почему ваша программа вызывает
abort
?
Ваша программа имеет неопределенное поведение. Это соответствует тому, что вы установили terminate_handler
соответственно, и, как вы заметили, программа приводит к вызову f()
но требуемое поведение для terminate_handler
функция:
Стандарт С ++ 03 18.6.3.1.2:
Обработчик terminate_handler должен прекратить выполнение программы без возврата
для звонящего.
Ваш terminate_handler
функция f
не удовлетворяет этому условию и, следовательно, приводит к неопределенному поведению, и технически возможно, что вы можете получить любое поведение, которое ваша реализация выберет для вызова abort
в этой ситуации. Ничто не мешает этому.
Может кто-нибудь сказать мне, когда вызывается terminate (), а когда неожиданно ()?
В вашем случае ваш обработчик завершения будет вызван. Вы можете проверить это Вот.
Что касается std::terminate()
пункт 15.5.1 / 1-2 содержит примечание, в котором приводится довольно исчерпывающий список ситуации, в которой оно вызывается (часть, выделенная жирным шрифтом, это то, что применимо в вашем случае):
1 В некоторых ситуациях обработка исключений должна быть прекращена для менее тонких методов обработки ошибок. [ Заметка:
Эти ситуации:— когда механизм обработки исключений, после завершения инициализации объекта исключения
но перед активацией обработчика для исключения (15.1) вызывает функцию, которая выходит через исключение,
или же— когда механизм обработки исключений не может найти обработчик для брошенного исключения (15.3) или
— когда при поиске обработчика (15.3) встречается самый внешний блок функции со спецификацией noexcept
что не допускает исключения (15.4), или— когда уничтожение объекта во время разматывания стека (15.2) заканчивается созданием исключения,
или же— когда инициализация нелокальной переменной со статической или потоковой продолжительностью хранения (3.6.2) завершается через
исключение или— когда уничтожение объекта со статическим или потоковым хранением завершается через исключение (3.6.3), или
— когда выполнение функции зарегистрировано
std::atexit
или жеstd::at_quick_exit
выход через исключение
(18,5) или— когда бросающее выражение без операнда пытается перебросить исключение, а исключение не выполняется
обработано (15.1), или— когда
std::unexpected
выдает исключение, которое не допускается ранее нарушенным
спецификация, и std :: bad_exception не включены в эту динамическую спецификацию исключений
(15.5.2) или— когда вызывается обработчик неожиданных исключений по умолчанию для реализации (D.11.1), или
— когда функция
std::nested_exception::rethrow_nested
вызывается для объекта, который захватил
без исключения (18.8.6), или— когда выполнение исходной функции потока завершается с помощью исключения (30.3.1.2), или
— когда деструктор или оператор присваивания копии вызывается для объекта типа std :: thread
это относится к присоединяемой теме (30.3.1.3, 30.3.1.4).
—Конечная записка]2 В таких случаях
std::terminate()
называется (18.8.3). […]
Что касается std::unexpected()
в соответствии с пунктом 15.4 / 9:
Всякий раз, когда выдается исключение, и при поиске обработчика (15.3) встречается самый внешний блок
функция со спецификацией исключения, которая не допускает исключения, то,— если спецификация исключения является динамической спецификацией исключения, функция
std::unexpected()
является
называется (15.5.2),— иначе вызывается функция std :: terminate () (15.5.1).