Я знаю, что к моим деструкторам обращаются нормальные, раскручиваются стека и когда исключения выдаются, но не, когда выход () называют.
Есть ли какие-либо другие случаи, куда мои деструкторы не собираются называться? Что относительно сигналов, таких как SIGINT или SIGSEGV? Я предполагаю, что для SIGSEGV, их не называют, но для SIGNINT они, как я знаю, какие сигналы раскрутят стек?
Есть ли какие-либо другие обстоятельства, где их не назовут?
Есть ли другие обстоятельства, при которых они [деструкторы] не будут вызываться?
Если функция или метод имеет спецификацию throw и выдает что-то, НЕ охватываемое спецификацией, по умолчанию выполняется немедленный выход. Стек не разматывается и деструкторы не вызываются.
Сигналы POSIX представляют собой конструкцию, специфичную для операционной системы, и не имеют понятия об области объекта C ++. Обычно вы не можете ничего сделать с сигналом, кроме, возможно, перехватить его, установить глобальную переменную флага, а затем обработать ее позже в вашем коде C ++ после выхода обработчика сигнала.
Последние версии GCC позволяют генерировать исключение из обработчиков синхронных сигналов, что действительно приводит к ожидаемому процессу раскрутки и уничтожения. Однако это очень зависит от операционной системы и компилятора
Другой случай, когда они не будут вызываться, - это если вы используете полиморфизм и не сделали ваши базовые деструкторы виртуальными.
abort
завершает программу без выполнения деструкторов для объектов с автоматической или статической продолжительностью хранения, как говорит Стандарт. В других случаях вам следует ознакомиться с документами, относящимися к конкретной реализации.
Сигнал сам по себе не повлияет на выполнение текущего потока и отсюда и вызов деструкторов, потому что это другой контекст выполнения со своим собственным стеком, где ваши объекты не существуют. Это похоже на прерывание: оно обрабатывается где-то вне вашего контекста выполнения, и, если оно обработано, управление возвращается вашей программе.
Как и в случае с многопоточностью, C ++ язык не знает понятия сигналов. Эти два полностью ортогональны друг другу и определены двумя несвязанными стандартами. Как они взаимодействуют, зависит от реализации, если это не нарушает ни один из стандартов.
В качестве примечания: другой случай, когда деструктор объекта не вызывается, - это когда его конструктор генерирует исключение. Однако деструкторы членов по-прежнему будут вызываться.
В основном есть две ситуации, когда вызываются деструкторы: в стеке раскрутка в конце функции (или в исключительных случаях), если кто-то (или счетчик ссылок) вызывает удаление.
Одна особая ситуация может быть обнаружена в статических объектах - они уничтожаются в конце программы через at_exit, но это все еще вторая ситуация.
Какой сигнал оставляет прохождение at_exit, может зависеть, kill -9 немедленно завершит процесс, другие сигналы сообщат ему о выходе, но как именно зависит от обратного вызова сигнала.
Стандарт C++ ничего не говорит о том, как должны обрабатываться конкретные сигналы - многие реализации могут не поддерживать SIGINT
и т.д. Деструкторы не будут вызываться, если вызваны exit()
или abort()
или terminate()
.
Правка: Я только что провел быстрый поиск в стандарте C++ и не могу найти ничего, что бы определяло, как сигналы взаимодействуют с временем жизни объектов - возможно, кто-то, кто лучше меня разбирается в стандартах, сможет что-то найти?
Дальнейшая правка: Отвечая на другой вопрос, я нашел вот это в стандарте:
При выходе из области видимости (как бы это ни было выполненным), деструкторы (12.4) вызываются для всех созданных объектов с автоматической продолжительностью хранения (3.7.2) (именованные объекты или временные объекты) которые объявлены в этой области видимости, в обратном порядке их объявления.
Таким образом, кажется, что деструкторы должны вызываться при получении сигнала.