Когда С++ заканчивает обработчик правой Thing (TM)?

В стандарте С++ предусмотрена функция std::set_terminate, которая позволяет вам указать, какую функцию std::terminate нужно вызвать. std::terminate следует вызывать только в ужасных обстоятельствах и, конечно же, ситуации, описанные стандартом, когда они называются, являются ужасными (например, неперехваченное исключение). Когда std::terminate действительно называется ситуацией, кажется, что это похоже на отсутствие памяти - на самом деле вы не можете очень разумно сделать.

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

Когда используется обработчик terminate Right Thing (TM)?

Обновление: Люди, заинтересованные в том, что можно сделать с помощью пользовательских обработчиков terminate, могут найти полезный этот не переносимый трюк.

Ответ 1

Это просто оптимистично:

но для большинства ресурсов это должно автоматически обрабатываться ОС при выходе из процесса

О единственных ресурсах, которые автоматически обрабатывает ОС, являются "Файловые дескрипторы" и "Память" (и это может различаться в разных ОС). Практически все остальные ресурсы (и если у кого-то есть список ресурсов, которые автоматически обрабатываются ОС I любил бы это) должен быть вручную выпущен ОС.

Лучше всего избегать выхода с помощью функции terminate() и попробовать контролируемое закрытие, заставляя стеки правильно раскручиваться. Это позволит убедиться, что все деструкторы вызваны правильно и ваши ресурсы освобождены (через деструкторы).

О единственном, что я бы сделал, это зарегистрировать проблему. Так что, когда это произойдет, я могу вернуться и исправить код, чтобы он не повторился. Мне нравится, что мой код отлично раскручивает стек для освобождения ресурсов, но это мнение некоторых людей, таких как внезапные остановки, когда что-то идет плохо.

Мой список при вызове terminate:

В общем случае он вызывается, когда механизм обработки исключений не может найти обработчик для вызванного исключения. Некоторые конкретные примеры:

  • Исключение исключает main()
    • Примечание. Реализация определяется, разблокирован ли стек. Таким образом, я всегда поймаю в основном, а затем реконструирую (если я явно не обрабатываю). Таким образом, я гарантирую разматывание стека (на всех платформах) и все еще получаю преимущества механизма обработки исключений ОС.
  • Два исключения распространяются одновременно.
    • Исключение исключает десаструктор, пока распространяется другое исключение.
    • Выраженное выражение генерирует исключение
  • Исключение до или после main.
    • Если исключение исключает конструктор/деструктор глобального объекта.
    • Если исключение исключает деструктор статической переменной функции. (т.е. будьте осторожны с конструкторами/деструкторами нелокального статического объекта)
    • Исключение исключает функцию, зарегистрированную с помощью atexit().
  • Возвращение, когда в настоящее время не распространяется какое-либо исключение.
  • Необязательное исключение исключает метод/функцию, которая имеет список спецификаторов исключений.
    • с помощью неожиданного.

Ответ 2

Как и в заявлении, сделанном в ответе , о единственном, что я делаю в пользовательском обработчике завершения, записывается проблема, поэтому я могу определить и исправить нарушение код. Это единственный экземпляр, который я обнаружил, что использование пользовательского обработчика завершения - это правое.


Поскольку он определяется реализацией независимо от того, разрывается ли стек до того, как вызывается std::terminate(), я иногда добавляю код для генерации обратной трассы, чтобы найти неперехваченное исключение 1.

1) Это, похоже, работает для меня при использовании GCC на платформах Linux.

Ответ 3

Я думаю, что правильным вопросом было бы, как избежать вызовов для завершения обработчика, а не когда его использовать.