Pregunta

Tengo una clase PHP que crea una imagen PNG sobre la marcha y la envía al navegador. El manual de PHP dice que necesito asegurarme de que la función imagedestroy se llame al final para liberar la memoria. Ahora, si no estuviera usando una clase, tendría un código como este:

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

Sin embargo, creo que el lugar apropiado para mi clase sería hacer una llamada a imagedestroy en el destructor de la clase.

No pude averiguar si los destructores se llaman de la misma manera que las funciones de apagado. Por ejemplo, si la ejecución se detiene cuando el usuario presiona el botón STOP en el navegador.

Nota: cualquier cosa que escriba en su respuesta, señale algún artículo o página de manual (URL) que lo admita.

¿Fue útil?

Solución

Acabo de probar con Apache, PHP se usa como módulo de Apache. Creé un bucle sin fin como este:

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

Esto es lo que descubrí:

  • presionar el botón STOP en Firefox no detiene este script
  • Si apago Apache, no se llama al destructor
  • Se detiene cuando alcanza PHP max_execution_time y no se llama al diseñador

Sin embargo, haciendo esto:

<?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
}
?>
Se llama a

shutdown_func. Esto significa que el diseño de clase no es tan bueno como las funciones de apagado.

Otros consejos

Basado en el principio de que debe terminar lo que comienza , Diría que el destructor es el lugar correcto para la llamada gratuita.

El destructor se llamará cuando el objeto esté desechado, mientras que una función de apagado no se llamará hasta finaliza la ejecución del script. Como señaló Wolfie, esto no sucederá necesariamente si detiene por la fuerza el servidor o el script, pero en ese momento, la memoria asignada por PHP se liberará de todos modos.

También señalado por Wolfie, PHP liberará recursos de script cuando el script se cierre, por lo que si solo está instanciando uno de estos objetos, entonces probablemente no notará una diferencia masiva. Sin embargo, si luego terminas creando instancias de estas cosas, o lo haces en un bucle, entonces probablemente no quieras tener que preocuparte por un aumento repentino en el uso de la memoria, así que por el bien de la cordura futura, vuelvo a mi recomendación original; ponlo en el destructor.

Recientemente tuve problemas con esto ya que estaba tratando de manejar la destrucción específicamente para el caso en el que el servidor experimenta un tiempo de espera y quería incluir datos de clase en el registro de errores. Recibiría un error al hacer referencia a & amp; $ this (aunque lo he visto en algunos ejemplos, posiblemente un problema de versión o un efecto secundario de Symfony), y la solución que se me ocurrió fue bastante limpia:

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 esto ayude a alguien!

Creo que una gran cosa que te has perdido es que toda la memoria que PHP ha asignado durante la ejecución del script se libera una vez que el script termina. Incluso si el usuario presiona el botón de detención, PHP procesa el script hasta que esté terminado, lo devuelve al demonio HTTP para que se lo sirva al visitante (o no, dependiendo de qué tan inteligente sea el demonio).

Por lo tanto, liberar explícitamente la memoria al final de la ejecución del script es un poco redundante. Algunos podrían argumentar que sería bueno hacerlo, pero aún es redundante.

Pero, en el tema de los destructores de clases, se les llama cada vez que se destruye el objeto, ya sea explícitamente por unset () o al finalizar / finalizar el script.

La recomendación del desarrollador de liberar explícitamente la memoria utilizada en la manipulación de imágenes es segura para asegurarse absolutamente de no tener una pérdida de memoria, ya que los mapas de bits pueden forzar el lado de la memoria (altura * ancho * profundidad de bits * 3 (+ 1 si tiene un canal alfa))

Para satisfacer sus necesidades de Wikipedian:

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top