Pergunta

Eu tenho uma classe PHP que cria uma imagem PNG em tempo real e envia-lo para o navegador. manual do PHP diz que eu preciso ter certeza de que imagedestroy função é chamada no final para liberar a memória. Agora, se eu não estivesse usando uma classe, eu teria algum código como este:

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

No entanto, acredito que o lugar apropriado para minha classe seria colocar uma chamada para imagedestroy na classe destruidor.

Eu não conseguiram descobrir se destruidores são chamados as mesmas funções como desligamento faz? Por exemplo, se a execução é interrompida quando o usuário pressiona o botão STOP no navegador.

Nota:. Tudo o que você escreve em sua resposta, por favor, apontam para algum artigo ou página manual (URL) que o suporta

Foi útil?

Solução

Eu só testado com Apache, PHP está sendo usado como módulo do Apache. Eu criei um loop infinito como esta:

<?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
}
?>

Aqui está o que eu descobri:

  • pressionando o botão STOP no Firefox não parar este script
  • Se eu desligar Apache, destruidor não obter chamado
  • Ele pára quando chega PHP max_execution_time e destuctor não obter chamado

No entanto, fazer isso:

<?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 é chamado. Então isso significa que a classe destuctor não é tão bom como funções de desligamento.

Outras dicas

Com base no princípio de que você deve termine o que começou , eu diria que o destruidor é o lugar correto para a chamada livre.

O destructor será chamado quando o objeto é eliminados, enquanto que uma função desligamento não será chamado até acabamentos execução do script. Como observado por Wolfie, estes não serão necessariamente aconteceria se você força interromper o servidor ou o script, mas naquele tempo, a memória alocada pelo PHP será liberado de qualquer maneira.

Também observado por Wolfie, PHP irá liberar recursos de script quando o fecha de script, por isso, se você está instanciar apenas um desses objetos, então você provavelmente não notar uma diferença enorme. No entanto, se você mais tarde acabam instanciar essas coisas, ou fazê-lo em um loop, então você provavelmente não quer ter que se preocupar com um aumento repentino no uso de memória, por isso, para o bem do futuro sanidade, volto ao meu recomendação original; colocá-lo no processo de destruição.

Recentemente, tive problemas com isso como eu estava tentando destruição alça especificamente para o caso em que o servidor experimenta um tempo limite e eu queria incluir dados de classe no log de erro. Gostaria de receber um erro ao fazer referência a & $ this (embora eu já vi isso feito em poucos exemplos, possivelmente um problema de versão ou um efeito colateral symfony), e a solução que eu vim com era bastante limpo:

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);
        }
    }

    ...

Espero que isso ajude alguém!

Eu acho que uma grande coisa que você perdeu é que toda a memória PHP alocou durante a execução do script é libertado uma vez que os termina script. Mesmo se o usuário pressiona o botão de stop, PHP processa o script até que esteja terminado, dá-lo de volta para o HTTP daemon para ser servido para o visitante (ou não, dependendo de quão inteligente o daemon é).

Assim, explicitamente liberando memória no final da execução do script é um pouco redundante. Alguns poderão argumentar que seria uma boa coisa a fazer, mas ainda é redundante.

Mas, sobre o tema da destruidores de classe, eles são chamados sempre que o objeto é destruído, quer explicitamente por unset() ou pelo script de conclusão / término.

A recomendação do desenvolvedor explicitamente liberar a memória usada na manipulação de imagens é certo só para ter a certeza absoluta de não ter um vazamento de memória, como bitmaps pode ser esticar no lado da memória das coisas (altura * largura profundidade * pouco * 3 (+ 1 se você tiver um canal alfa))

Para satisfazer as suas necessidades wikipedian:

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top