Когда обработчик завершения C ++ является правильным (TM)? - PullRequest
11 голосов
/ 29 июня 2009

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

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

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

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

Ответы [ 3 ]

7 голосов
/ 29 июня 2009

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

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

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

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

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

Мой список, когда вызывается терминат:

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

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

По аналогии с заявлением, сделанным в ответе Мартина Йорка , единственное, что я делаю в пользовательском обработчике завершения, - это регистрация проблемы, чтобы я мог идентифицировать и исправить код, вызывающий ошибку. Это единственный случай, когда я обнаружил, что использование пользовательского обработчика завершения - это Right Thing .


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

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

0 голосов
/ 29 июня 2009

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

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