Frage

Ich habe eine PHP-Klasse, die ein PNG-Bild on the fly erstellt und sendet sie an Browser. PHP-Handbuch sagt, dass ich sicherstellen müssen, dass imagedestroy Funktion am Ende genannt wird, den Speicher freizugeben. Nun, wenn ich nicht eine Klasse verwenden, würde ich einige Code wie folgt aussehen:

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

Ich glaube jedoch, dass geeigneter Ort für meine Klasse einen Aufruf an imagedestroy in der Klasse destructor zu platzieren wäre.

Ich konnte nicht herausfinden, ob Destruktoren die gleiche Art und Weise Shutdown Funktionen aufgerufen hat? Zum Beispiel, wenn die Ausführung stoppt, wenn Benutzer die STOP-Taste im Browser.

Hinweis: was auch immer Sie in Ihrer Antwort schreiben, zeigen Sie auf einige Artikel oder manuelle Seite (URL), die es unterstützt

.
War es hilfreich?

Lösung

ich gerade getestet mit Apache, PHP als Apache-Modul verwendet wird. Ich habe eine Endlosschleife wie folgt aus:

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

Hier ist, was ich herausgefunden habe:

  • Drücken STOP-Taste in Firefox nicht dieses Skript stoppen
  • Wenn ich Apache heruntergefahren, destructor nicht genannt bekommt
  • Es hört auf, wenn es PHP max_execution_time und destuctor erreicht nicht aufgerufen

Allerdings tun dies:

<?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 wird aufgerufen. Dies bedeutet also, dass die Klasse destuctor als Shutdown-Funktionen sind nicht so gut.

Andere Tipps

basiert auf dem Prinzip, dass Sie sollten beenden, was Sie anfangen ich die destructor würde sagen, der richtige Ort für den freien Anruf ist.

Die destructor aufgerufen wird, wenn das Objekt entsorgt, wohingegen eine Abschaltfunktion rel="nofollow bis nicht aufgerufen wird, Skriptausführung beendet. Wie von Wolfie erwähnt, werden diese nicht unbedingt passieren, wenn Sie mit Gewalt auf den Server oder das Skript stoppen, aber zu dieser Zeit, die von PHP zugewiesenen Speicher ohnehin befreit werden.

Auch von Wolfie erwähnt, wird PHP-Skript Ressourcen freisetzen, wenn das Skript schließt, so wenn Sie nur eines dieser Objekte instanziiert wird, dann würden Sie wahrscheinlich keinen großen Unterschied bemerken. Wenn Sie jedoch später diese Dinge tun am Ende instanziiert wird, oder tun dies in einer Schleife, dann haben Sie wahrscheinlich nicht wollen, um einen plötzlichen Anstieg in der Speichernutzung, so im Interesse der Zukunft geistige Gesundheit zu kümmern haben, ich kehre zu meinem ursprüngliche Empfehlung; steckt es in der destructor.

Vor kurzem hatte ich Mühe mit dieser als ich versuche Zerstörung speziell für den Fall zu behandeln, in dem der Server ein Timeout erfährt, und ich wollte Klassendaten im Fehlerprotokoll aufzunehmen. Ich würde eine Fehlermeldung erhalten, wenn Referenzierung auf diesem $ (obwohl ich habe es in einigen Beispielen getan gesehen, möglicherweise eine Version Ausgabe oder eine symfony Nebenwirkung) und die Lösung kam ich mit war ziemlich sauber:

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

    ...

Hoffe, das hilft jemand!

Ich denke, eine große Sache, die Sie verpasst haben, ist, dass der gesamte Speicher PHP während der Skriptausführung zugewiesen hat freigegeben wird, sobald das Skript beendet. Selbst wenn der Benutzer den Stopp-Knopf drückt, PHP verarbeitet das Skript, bis es fertig ist, es Dämon zurück an den HTTP gibt dem Besucher bedient werden (oder auch nicht, je nachdem, wie klug der Dämon ist).

So explizit Speicher am Ende der Skriptausführung Freisetzung ist ein bisschen überflüssig. Man könnte argumentieren, dass es eine gute Sache zu tun wäre, aber es ist immer noch redundant.

Aber zum Thema Klasse Destruktoren sie genannt werden, wenn das Objekt zerstört wird, entweder explizit durch unset() oder Skript Abschluss / Kündigung.

Die Empfehlung des Entwicklers zu befreien explizit den Speicher in Bildmanipulation aufgebraucht ist sicher nur um absolut sicher, nicht zu einem Speicherverlust zu haben, als Bitmaps auf der Speicherseite der Dinge (Höhe * Breite * Bittiefe strengt werden kann * 3 (+ 1, wenn Sie einen alpha-Kanal haben))

Ihre Wikipedianer erfüllen muss:

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top