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

StackOverflow https://stackoverflow.com/questions/151660

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

Другие советы

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

Вы должны явно вызвать родительский элемент::__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 столкнется с ошибкой сегментации или возникнет какая-то другая внутренняя ошибка, то все ставки отменяются.

Если ты хочешь понять текущий реализация "последовательности завершения работы", см. https://stackoverflow.com/a/14101767.Обратите внимание, что эта реализация может измениться в будущих версиях PHP.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top