2017-12-29 2 views
1

Während der Garbage Collector in PHP mit Referenzen zu studieren, habe ich nicht verstanden, was die Bereinigung Probleme von Referenzen mit dem Garbage Collector, die here erwähntenProbleme mit Referenzen in PHP

$a = array('one'); 
    $a[] =& $a; 
    xdebug_debug_zval('a'); 
    unset($a); 

der Verweis auf diesem Code und Abschnitt sagte

Obwohl kein Symbol in irgendeinem Bereich auf diese Struktur verweist, kann es nicht bereinigt werden, da das Array-Element "1" immer noch auf das gleiche Array zeigt. Da kein externes Symbol darauf zeigt, kann ein Benutzer diese Struktur nicht bereinigen. So bekommst du ein Speicherleck.

nach PHP Referenzen zu studieren, habe ich gelernt, dass unset die Variable Mittel, um die Bindung zwischen dem Variablennamen und Inhalt abgeholzt, so nach dem folgenden Code:

$a = array('one'); 
    $a[] =& $a; 
    unset($a); 

die ganze Variable einen wird $ nicht mit dem Inhalt verbunden sein, und aufgrund der Entfernung des gesamten Arrays werden auch seine Inhaltsreferenzen oder Variablen entfernt. Wo ist also das Aufräumproblem?

beachten Sie, dass nach dem folgenden Code, hier xdebug Funktion erzeugt bedeutet, dass zwei Verweise oder Zeiger oder Bindungen freigesetzt werden, was beweist, dass es nicht Bereinigung Problem ist:

$a = array('one'); 
    $a[] =& $a; 
    xdebug_debug_zval('a'); 

Referenzen i studierte von:

  1. Manual
  2. Toptal Article
  3. Sitepoint

Antwort

0

Der Punkt ist, kann diese nicht entfernt werden, da gibt es noch einen Zeiger auf var $a. Da es keine einfache Lösung gibt zu erkennen, dass dieser Zeiger innerhalb $a definiert ist, kann der für $a reservierte Speicher nicht frei sein.

enter image description here

Wie in diesem Bild gesehen, gibt es ein Zeiger aus dem Inneren der Matrix an das Array selbst. Dieser Zeiger (der den Refcount inkrementiert) existiert sogar, wenn Sie den Ref auf $a zurücksetzen.

$a = array('one'); // refcount for a = 1 
$a[] =& $a; // refcount for a = 2 
unset($a); // refcount for a = 1, but there's remains no usable pointer for the php user 

Eine einfache Schleife

dieses Verhalten zeigen, könnte
$start = memory_get_usage(); 

for ($i = 0; $i < 100000; $i++) { 
    $a = ['test']; 
    // if you remove this line, the memory usage is 0, if not 4000000 
    $a[] = &$a; 
    unset($a); 
} 

echo memory_get_usage() - $start; 
+0

php den Speicher von spezifischer Referenz befreit, wenn es keine Hinweise auf diese Referenz, also, wenn Sie das gesamte Array entfernen (das hält die zweite Referenz) , dann löscht php diesen zval-Container als keine Zeiger darauf. Eine weitere Klarstellung: Wenn das übergeordnete Array auf einen bestimmten zval-Container verweist und ein Element (untergeordnetes Element) aufweist, das auf denselben zval-Container verweist, haben Sie das übergeordnete Element entfernt, das das untergeordnete Element enthält. Dann gibt es keine Zeiger auf den gemeinsamen zval-Container. Wo also die Aufräumprobleme? – youhana

+0

* Wenn Sie also das gesamte Array entfernen (das die zweite Referenz enthält), dann löscht php diesen zval Container als keine Zeiger darauf * falsch!Es gibt immer noch einen Zeiger auf das Array, das im Array gespeichert ist – Philipp