В чем разница между std :: quick_exit и std :: abort и зачем нужен std :: quick_exit? - PullRequest
37 голосов
/ 18 марта 2012

C ++ 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, и позволяет установить возвращаемый статус?

Каково было обоснование для введения этой функции?

Ответы [ 3 ]

36 голосов
/ 18 марта 2012

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

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

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

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

20 голосов
/ 18 марта 2012

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

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

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

2 голосов
/ 18 марта 2012

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_», оно быстрее, так как пропускает этап очистки.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...