Функция гарантированно вызывается в C ++ во время внезапного завершения или выхода - PullRequest
6 голосов
/ 01 августа 2011

Какая функция в C ++ гарантированно будет вызвана во время внезапного завершения или выхода, что может выполнить очистку

Ответы [ 8 ]

8 голосов
/ 01 августа 2011

В зависимости от того, что вы подразумеваете под «внезапным завершением», существует несколько различных вариантов:

  • Глобальные деструкторы будут вызываться при нормальном завершении (возврат из main иливызов exit()).
  • atexit() регистрирует функцию, вызываемую при нормальном завершении.
  • std::set_terminate регистрирует функциюэто будет вызвано, когда исключение выдается, но не перехвачено, или когда «обработка исключения должна быть прервана по какой-либо другой причине».
  • sigaction() регистрирует функции, которые вызываются, когда вашПрограмма получает сигналы , многие из которых обычно внезапно завершают вашу программу.Обработчики сигналов могут вызываться, когда программа находится во внутренне несовместимом состоянии, и поэтому крайне ограничены в своих возможностях.Например, они не могут делать ничего, что могло бы выделить память.Кроме того, этот API недоступен в Windows;есть эквиваленты, но я не знаком с ними.

Обратите внимание, что все широко используемые операционные системы предоставляют по крайней мере один способ внезапного завершения вашей программы, который не может быть перехвачен из вашей программы.код.Например, Unix имеет сигнал 9 (SIGKILL), для которого вы не можете зарегистрировать обработчик. Это функция, а не ошибка. Вам, пользователю, нужен способ заставить процесс уйти, даже если он сделал все, что в его силах, чтобы сделать себя неуничтожимым.Кроме того, никакой код не может защитить ваш процесс, когда домашний кролик пользователя грызет шнур питания компьютера.Из-за этого может быть лучше использовать ваше время, чтобы спроектировать программу для восстановления после сбоев , а не пытаться выполнить очистку при возникновении сбоя.Подробнее об этом см. В этой статье « Конструкция только для сбоя ».

2 голосов
/ 01 августа 2011

Читайте о atexit здесь . Однако он не будет вызываться в всех случаях (например, вызов abort не вызовет функцию, которую вы зарегистрировали с помощью atexit).

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

1 голос
/ 01 августа 2011
int main()
{
    try
    {
        // all your code here
    }
    catch(...)
    {
        // cleanup
    }
    return 0;
}
1 голос
/ 01 августа 2011

Вы ищете set_terminate().

http://www.cplusplus.com/reference/std/exception/set_terminate/

В том же заголовке есть другие похожие функции, которые можно использовать для дополнительных сценариев.

0 голосов
/ 01 августа 2011

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

http://www.gnu.org/s/hello/manual/libc/Signal-Handling.html

Написание собственных обработчиков сигналов позволит вам определить, что вы хотите делать, когда захватывается определенный сигнал. Как уже говорилось, есть некоторые, которые не могут быть отменены, и по уважительной причине. Вы не хотите позволять кому-либо переопределять kill -9 просто потому, что может быть создана программа, которую невозможно убить. Тем не менее, прямой сигнал уничтожения или что-то вроде ctrl-c, ctrl-d и т. Д. Может быть перехвачено и обработано любым способом.

0 голосов
/ 01 августа 2011

Нет функции, которая фиксирует все сценарии и работает на всех платформах. Если вам нужно что-то для Windows, вам также придется обрабатывать SEH (структурированную обработку исключений). Вам нужно будет определить и установить обработчики для различных сценариев (SEH, C ++ Exceptions, SIGABRT, Terminate и т. Д.), Которые выполняют общий код очистки и. Проверьте ответ Зака ​​здесь для обработки сигналов SIGABRT.

Для SEH вы можете добавить конвертер SE для обработки исключений SE и преобразовать их в исключения C ++, посмотрите _set_se_translator для получения дополнительной информации об обработке исключений SEH.

Вы можете обратиться к этой документации для обработчика set_terminate и , это хорошая ссылка для set_unexpected .

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

В конце я бы рекомендовал использовать для этой цели несколько существующих библиотек, мне нравится crashrprt .

0 голосов
/ 01 августа 2011

Я не эксперт, и я просто знаю несколько вещей о C ++, но я знаю, что вы можете создавать дескрипторы в Unix и C, чтобы обнаруживать конкретный сигнал, а затем выполнять функцию, а затем завершать программу с помощью команды " выход (n) ", например.

Вы можете сделать это, используя сигнал или sigaction , но проблема в том, что этот метод можно использовать только для любого сигнала, кроме SIGKILL или SIGSTOP.

0 голосов
/ 01 августа 2011

В какой среде вы работаете? под резким ты имеешь в виду сигнал Ctrl + C или kill -9? В Unix / Linux вы можете замаскировать некоторые сигналы и предоставить обработчики, но, насколько я знаю, вы не можете замаскировать весь сигнал (9 - пример сигнала, который не может быть замаскирован, и он внезапно убьет ваш процесс)

Может быть доступно некоторое переопределение даже более низкого уровня при работе с ОС, но я не знаком с этим.

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