Вопрос

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

function shutdown_func() 
{
    global $img;
    if ($img)
        imagedestroy($img);
}
register_shutdown_function("shutdown_func");

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

Мне не удалось выяснить, вызываются ли деструкторы так же, как функции завершения работы?Например, если выполнение останавливается, когда пользователь нажимает кнопку СТОП в браузере.

Примечание:Что бы вы ни написали в своем ответе, укажите на какую-нибудь статью или страницу руководства (URL), которая это поддерживает.

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

Решение

Я только что тестировал Apache, PHP используется в качестве модуля Apache.Я создал бесконечный цикл следующим образом:

<?php
class X
{
    function __destruct()
    {
        $fp = fopen("/var/www/htdocs/dtor.txt", "w+");
        fputs($fp, "Destroyed\n");
        fclose($fp);
    }
};

$obj = new X();
while (true) {
    // do nothing
}
?>

Вот что я узнал:

  • нажатие кнопки СТОП в Firefox не останавливает этот скрипт
  • Если я выключу Apache, деструктор не будет вызван
  • Он останавливается, когда достигает PHP max_execution_time, и дестуктор не вызывается.

Однако, делая это:

<?php
function shutdown_func() {
    $fp = fopen("/var/www/htdocs/dtor.txt", "w+");
    fputs($fp, "Destroyed2\n");
    fclose($fp);
}
register_shutdown_function("shutdown_func");

while (true) {
    // do nothing
}
?>

Shutdown_func вызывается.Это означает, что дестуктор класса не так хорош, как функции завершения работы.

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

Исходя из принципа, что вы должны завершить начатое Я бы сказал, что деструктор - правильное место для бесплатного звонка.

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

Также отметил Вольф, PHP освободит ресурсы скрипта при закрытии скрипта, поэтому, если вы создаете экземпляр только одного из этих объектов, то вы, вероятно, не заметите существенной разницы. Тем не менее, если позже вы в конечном итоге создадите эти экземпляры или сделаете это в цикле, то вам, вероятно, не нужно беспокоиться о внезапном скачке использования памяти, поэтому ради будущего здравого смысла я вернусь к своему оригинальная рекомендация; положить его в деструктор.

Недавно у меня возникли проблемы с этим, поскольку я пытался обработать уничтожение специально для случая, когда сервер испытывает таймаут, и я хотел включить данные класса в журнал ошибок. Я получаю сообщение об ошибке при обращении к & amp; $ this (хотя я видел это в нескольких примерах, возможно, проблема с версией или побочным эффектом Symfony), и решение, которое я нашел, было довольно чистым:

class MyClass
{
    protected $myVar;

    /**
     * constructor, registers shutdown handling
     */
    public function __construct()
    {
        $this->myVar = array();

        // workaround: set $self because $this fails
        $self = $this;
        // register for error logging in case of timeout
        $shutdown = function () use (&$self) {
            $self->shutdown();
        };
        register_shutdown_function($shutdown);
    }

    /**
     * handle shutdown events
     */
    public function shutdown()
    {
        $error = error_get_last();
        // if shutdown in error
        if ($error['type'] === E_ERROR) {
            // write contents to error log
            error_log('MyClass->myVar on shutdown' . json_encode($this->myVar), 0);
        }
    }

    ...

Надеюсь, это кому-нибудь поможет!

Я думаю, вы упустили одну важную вещь: вся память, выделенная PHP во время выполнения сценария, освобождается после его завершения.Даже если пользователь нажимает кнопку «Стоп», PHP обрабатывает сценарий до его завершения и возвращает его демону HTTP для передачи посетителю (или нет, в зависимости от того, насколько умен этот демон).

Таким образом, явное освобождение памяти в конце выполнения скрипта немного избыточно.Некоторые могут возразить, что это было бы хорошо, но это по-прежнему излишне.

Но, что касается деструкторов классов, они вызываются всякий раз, когда объект уничтожается, либо явно unset() или при завершении/завершении сценария.

Разработчик рекомендует явно освободить память, используемую при манипуляциях с изображениями, просто для того, чтобы быть уверенным в отсутствии утечки памяти, поскольку растровые изображения могут создавать нагрузку на память (высота * ширина * разрядность * 3 (+ 1 если у тебя есть альфа-канал))

Чтобы удовлетворить ваши потребности в Википедии:

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