В PHP5 метод __destruct () гарантированно вызывается для каждого экземпляра объекта? Могут ли исключения в программе предотвратить это?
Деструктор вызывается, когда все ссылки освобождаются или когда сценарий завершается. Я предполагаю, что это означает, что сценарий заканчивается должным образом. Я бы сказал, что критические исключения не гарантируют, что деструктор будет вызван.
Документация PHP немного тонкая, но она говорит, что Исключения в деструкторе вызовут проблемы.
Также стоит упомянуть, что в случае подкласса, который имеет свой собственный деструктор, родительский деструктор не вызывается автоматически.
Вы должны явно вызвать parent :: __ destruct () из метода подкласса __destruct (), если родительский класс выполняет любую необходимую очистку.
По моему опыту, деструкторы всегда будут вызываться в PHP 5.3, но следует предупредить, что если какой-то фрагмент кода вызывает exit () или если возникает фатальная ошибка, PHP вызовет деструкторы в «любом» порядке (я думаю, что фактический порядок – это порядок в память или порядок памяти, зарезервированный для объектов. На практике этот порядок почти всегда проблематичен). Это упоминается как «последовательность выключения» в документации PHP.
Документация деструкторов в PHP говорит:
PHP 5 представляет концепцию деструктора, аналогичную концепции других объектно-ориентированных языков, таких как C ++. Метод деструктора будет вызываться, как только нет других ссылок на конкретный объект или в любом порядке во время последовательности выключения.
В результате, если у вас есть класс X, который содержит ссылку на Y, деструктор X можно назвать ПОСЛЕ того, как деструктор Y уже вызван. Надеюсь, ссылка на Y была не такой важной … Официально это не ошибка, потому что она была задокументирована.
Однако очень сложно решить эту проблему, потому что официально PHP не дает возможности узнать, вызван ли деструктор нормально (деструкторы вызываются в правильном порядке), или деструкторы вызываются в «любом» порядке, где вы не можете использовать данные из ссылочных объектов, потому что они могут были уже уничтожены. Можно было обойти эту нехватку обнаружения с помощью debug_backtrace () и изучить стек. Отсутствие нормального стека, кажется, подразумевает «последовательность выключения» с PHP 5.3, но это тоже не определено. Если у вас есть циклические ссылки, деструкторы этих объектов вообще не будут вызываться с PHP 5.2 или меньше и будут вызваны в «любом» порядке во время «последовательности выключения» в PHP 5.3 или выше. Для круговых ссылок не существует логически «правильного» порядка, поэтому «любой» порядок для них хорош.
Есть некоторые исключения (в конце концов, это PHP):
exit()
вызывается в другом деструкторе, любые оставшиеся деструкторы не будут вызваны ( http://php.net/manual/en/language.oop5.decon.php ) FATAL
встречается в любом месте (причиной может быть множество возможных причин, например попытка удалить исключение из любого другого деструктора) Конечно, если PHP-движок сталкивается с ошибкой сегментации или какой-либо другой внутренней ошибкой, тогда все ставки отключены.
Существует текущая ошибка с циклическими ссылками, которая останавливает метод destruct, называемый неявно. http://bugs.php.net/bug.php?id=33595 Это должно быть исправлено в 5.3
Используйте функцию выключения, если вы хотите точно убедиться: register_shutdown_function ()