Когда обработчик завершения C ++ является правильной вещью (TM)?

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

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

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

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


person Joseph Garvin    schedule 29.06.2009    source источник
comment
std :: terminate должен вызываться только в ужасных обстоятельствах, и, конечно же, ситуации, описанные в стандарте, когда он вызывается, ужасны (например, неперехваченное исключение).   -  person xian    schedule 29.06.2009
comment
Вы имеете в виду неожиданное исключение: msdn.microsoft.com/en- us / library / awbt5tew (VS.80) .aspx.   -  person Martin York    schedule 29.06.2009
comment
Нет, он имеет в виду непойманное исключение.   -  person CiscoIPPhone    schedule 29.06.2009
comment
Ага, нашел. Фраза catch all: (Механизм обработки исключений не может найти обработчик для возникшего исключения.)   -  person Martin York    schedule 29.06.2009


Ответы (3)


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

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

Примерно единственными ресурсами, которые ОС обрабатывает автоматически, являются «Дескрипторы файлов» и «Память» (и это может варьироваться в зависимости от ОС). Практически все остальные ресурсы (и если у кого-то есть список ресурсов, которые автоматически обрабатываются ОС, мне бы это понравилось) должны быть вручную освобождены ОС.

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

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

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

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

  • An exception escapes main()
    • Note: It is implementation defined whether the stack is unwound here. Thus I always catch in main and then rethrow (if I do not explicitly handle). That way I guarantee unwinding of the stack (across all platforms) and still get the benefits of the OS exception handling mechanism.
  • Two exceptions propagating simultaneously.
    • An exception escapes a desatructor while another exception is propagating.
    • Выбрасываемое выражение генерирует исключение
  • An exception before or after main.
    • If an exception escapes the constructor/destructor of a global object.
    • Если исключение ускользает от деструктора статической переменной функции. (т.е. будьте осторожны с конструкторами / деструкторами нелокального статического объекта)
    • Исключение ускользает от функции, зарегистрированной с помощью atexit ().
  • Повторный выброс, если в настоящее время не распространяется исключение.
  • An unlisted exception escapes a method/function that has exception specifier list.
    • via unexpected.
person Martin York    schedule 29.06.2009
comment
На самом деле, мне было бы интересно увидеть список ресурсов, которые НЕ восстанавливаются современной ОС при завершении процесса. AFAIK, все ресурсы, такие как сокеты, мьютексы, восстанавливаются как Linux, так и Windows. Трудно представить себе, как у вас могла быть надежная серверная ОС, где этого не было. - person ; 29.06.2009
comment
Я считаю, что Нил прав. Конечно, C ++ не всегда запускается в современной ОС;) - person Joseph Garvin; 29.06.2009
comment
НЕ восстановлен огромен. Это что-то недостаточно низкое, чтобы им управляла ОС. Подключение к БДc, ссылки на ISS :-). Даже розетки не очень хорошо обрабатываются. В Linux. Если вы завершите работу приложения, прослушивающего сокет, этот сокет будет по-прежнему недоступен в течение нескольких минут, прежде чем ОС очистит его. В Windows файл не обрабатывается особенно хорошо. Как часто мне приходилось перезагружаться, потому что какое-то мертвое приложение все еще удерживает файл (дескриптор файла, возможно, был очищен, но файловая система все еще считает, что файл используется), что мешает мне удалить его. - person Martin York; 29.06.2009
comment
Но сокеты будут восстановлены - пауза заложена в архитектуре сокета, но ее тоже можно настроить. Я много работаю с ODBC, и у меня нет проблем с тем, что соединения с базой данных не закрываются (они, конечно, также обычно являются сокетами). Точно у меня нет проблем с файлами. Вы случайно не используете Windows 3.1 :-) - person ; 29.06.2009
comment
Начали вопрос, чтобы ответить на загадку. stackoverflow.com/questions/1060160/ - person Martin York; 29.06.2009
comment
Пауза может быть свойственной, но при правильном закрытии она будет равна 0. В случае с БД не все БД основаны на сокетах (вы полагаетесь на детали реализации (т.е. закрытие сокета распространяется на отдельные процессы, которые могут обнаружить закрытие)), это плохой стиль. Что происходит, когда вы переходите к внутрипроцессной БД, которая находится в памяти. Что касается корма для собак, то некоторые экспериментальные FS не так хороши, как другие. - person Martin York; 30.06.2009
comment
Файлы закрываются, когда приложение умирает. Большую часть времени дескриптор файла открыт в другом приложении, таком как Explorer или даже в системном процессе, если он был открыт через SMB. - person Jimbo; 30.06.2009
comment
В C ++ 11 и более поздних версиях также существует случай исключения исключения из std::thread основной функции, то есть либо функции, либо operator() вызываемого объекта, переданного конструктору std::thread. - person Daniel Schepler; 22.05.2020

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


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

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

person jschmier    schedule 14.04.2010

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

person Cătălin Pitiș    schedule 29.06.2009
comment
Спасибо за оценку. Но ... это не бессмысленно. Избегайте обработчика прерывания - это хорошая практика. - person Cătălin Pitiș; 29.06.2009
comment
Совершенно ясно (по крайней мере, для меня), что ОП уже это понимает. - person Not Sure; 29.06.2009