Подтвердить что ты не робот

В чем разница между std:: quick_exit и std:: abort и почему нужен std:: quick_exit?

С++ 11 представляет новый способ завершения выполнения программы - std::quick_exit.

Цитирование N3242 18.5 (стр. 461):

[[noreturn]] void quick_exit(int status) noexcept;

Эффекты: функции, зарегистрированные вызовами at_quick_exit, вызываются в обратном порядке их регистрации, за исключением того, что функция должны быть вызваны после любых ранее зарегистрированных функций, которые уже был вызван в то время, когда он был зарегистрирован. Объекты не должны быть уничтожен в результате вызова quick_exit. Если управление оставляет зарегистрированная функция, вызываемая quick_exit, потому что функция не предоставить обработчик для исключенного броска, terminate(). [Примечание: at_quick_exit может вызывать зарегистрированную функцию из другого чем тот, который его зарегистрировал, поэтому зарегистрированные функции должны не полагаться на тождество объектов с продолжительностью хранения потоков. - end note] После вызова зарегистрированных функций quick_exit вызывается _Exit(status). [Примечание: стандартные буферы файлов не очищаются. См.: ISO C 7.20.4.4. - конечная нота]

Поскольку определение std::abort(void) и std::_Exit(int status) отличается только возможностью передать статус родительскому процессу, он поднимает мой вопрос.

Означает ли это, что единственная разница в семантике между std::quick_exit и std::abort заключается в том, что std::quick_exit вызывает функции, зарегистрированные с помощью std::at_quick_exit, и позволяет установить возвращаемый статус?

В чем смысл введения этой функции?

4b9b3361

Ответ 1

Здесь есть хорошая запись я просто подытожу ее. Эта функция была добавлена, чтобы конкретно решить сложность окончательного завершения программы, когда вы используете потоки. По своей природе выход запускается очень асинхронным событием, пользователь закрывает пользовательский интерфейс, администратор отключает машину и т.д. Это происходит независимо от состояния потоков, начатых программой, они почти всегда находятся в очень непредсказуемом состоянии.

В идеальном мире функция main() программы просит, чтобы потоки выходили, как правило, сигнализируя о событии, ждет окончания потоков, а затем выходит из main() для чистого выключения через exit(). Этот идеал, однако, очень трудно достичь. Поток может быть похоронен глубоко внутри системного вызова, скажем, в ожидании завершения ввода/вывода. Или он блокирует объект синхронизации, который должен быть сигнализирован другим потоком в правильном порядке. Результат редко бывает приятным, реальные программы часто заходят в тупик при выходе. Или сбой при непредвиденном порядке выключения.

Там есть простой и очень заманчивый способ обхода проблемы: вместо этого вызовите _exit(). Kaboom, программа закончилась, операционная система впадает в шрапнель. Но явно без какой-либо очистки вообще, очень грязно, иногда с артефактами, такими как полузаписанный файл или незавершенная транзакция dbase.

std:: quick_exit() предлагает альтернативу. Подобно _exit(), но с еще возможностью выполнить какой-то код, независимо от того, что было зарегистрировано с помощью at_quick_exit.

Ответ 2

Обоснование std::quick_exit обсуждается в N1327 и N2440. Основные различия между quick_exit, _Exit и exit касаются обработки статических деструкторов и очистки важной информации до стабильного хранилища:

  • std::_Exit: не выполняет статические деструкторы или выполняет сброс критического IO.
  • std::exit: выполняет статические деструкторы и сбрасывает критический IO.
  • std::quick_exit: не выполняет статические деструкторы, но выполняет флеш критический IO.

(Как уже упоминалось, std::abort просто отправляет SIGABRT.)

Ответ 3

std::abort завершает ваше приложение без вызова каких-либо функций, зарегистрированных с помощью "at_exit/at_quick_exit". С другой стороны, std::quick_exit, как вы указали, вызовет функции, зарегистрированные с помощью std::at_quick_exit.

std::abort обычно прерывает ваше приложение, это нужно вызывать, когда происходит некоторая ненормальная ситуация, и ваше приложение должно быть закрыто без каких-либо очистки. Из документации std::abort:

Вызывает ненормальное завершение программы, если SIGABRT не обработчик сигнала передается в сигнал, и обработчик не возвращается.

Если вы хотите выполнить некоторые очистки, std::quick_exit будет более подходящим. Эта последняя функция также позволяет вам прекратить ваше приложение изящно, так как оно заканчивается вызовом std::_Exit вместо того, чтобы сигнализировать сигнал типа std::abort (который сигнализирует SIGABRT, что делает приложение ненормальным).

std::exit позволяет вам изящно выйти из приложения, одновременно очищая автоматические, локальные и статические переменные потока. std::quick_exit нет. Вот почему в названии есть "quick_", это быстрее, так как он пропускает фазу очистки.

Следовательно, существует фактическая семантическая разница между обеими функциями. Один останавливает приложение ненормально, а другой выполняет изящный выход, что позволяет вам делать некоторые очистки.