Подтвердить что ты не робот

Могу ли я доверять методу PHP __destruct()?

В PHP5 метод __destruct() гарантированно вызывается для каждого экземпляра объекта? Могут ли исключения в программе предотвращать это?

4b9b3361

Ответ 1

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

Документация PHP немного тонкая, но она говорит, что Исключения в деструкторе вызовут проблемы.

Ответ 2

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

Вы должны явно вызвать parent:: __ destruct() из подкласса __ destruct(), если родительский класс выполняет любую необходимую очистку.

Ответ 3

В моем опыте деструкторы всегда будут вызываться в PHP 5.3, но имейте в виду, что если какой-то фрагмент кода вызывает exit() или возникает фатальная ошибка, PHP вызовет деструкторы в "любом" порядке (я думаю, что фактический порядок это порядок в памяти или порядок памяти, зарезервированный для объектов. На практике этот порядок почти всегда проблематичен). Это упоминается как "последовательность выключения" в документации PHP.

Документация по деструкторам PHP:

PHP 5 представляет концепцию деструктора, аналогичную концепции других объектно-ориентированных языков, таких как С++. Метод деструктора будет вызываться, как только нет других ссылок на конкретный объект или в любом порядке во время последовательности выключения.

В результате, если у вас есть класс X, который содержит ссылку на Y, деструктор X можно вызвать ПОСЛЕ того, как деструктор Y уже был вызван. Надеюсь, ссылка на Y не была такой важной... Официально это не ошибка, потому что она была задокументирована.

Однако очень сложно обойти эту проблему, потому что официально PHP не дает возможности узнать, вызван ли деструктор нормально (деструкторы вызываются в правильном порядке), или деструкторы вызываются в "любом" порядке, где вы не можете использовать данные из ссылочных объектов потому что они уже были уничтожены. Можно было обойти эту нехватку обнаружения с помощью debug_backtrace() и изучить стек. Отсутствие нормального стека, кажется, подразумевает "последовательность выключения" с PHP 5.3, но это тоже undefined. Если у вас есть циклические ссылки, деструкторы этих объектов вообще не будут вызываться с PHP 5.2 или меньше и будут вызваны в "любом" порядке во время "последовательности выключения" в PHP 5.3 или выше. Для круговых ссылок не существует логически "правильного" порядка, поэтому "любой" порядок хорош для них.

Есть некоторые исключения (в конце концов это PHP):

  • Если exit() вызывается в другом деструкторе, любые оставшиеся деструкторы не будут вызываться (http://php.net/manual/en/language.oop5.decon.php)
  • Если ошибка FATAL происходит где-то (многие возможные причины, например попытка удалить исключение из любого другого деструктора, могут быть одной причиной)

Конечно, если движок PHP сталкивается с ошибкой сегментации или какой-либо другой внутренней ошибкой, тогда все ставки отключены.

Ответ 4

Существует текущая ошибка с циклическими ссылками, которая останавливает метод destruct, называемый неявно. http://bugs.php.net/bug.php?id=33595 Его следует зафиксировать в 5.3

Ответ 5

Используйте функцию выключения, если вы хотите точно убедиться: register_shutdown_function()