<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/features.gc.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'de',
  ),
  'this' => 
  array (
    0 => 'features.gc.refcounting-basics.php',
    1 => 'Grundlagen des Z&auml;hlens von Referenzen',
    2 => 'Grundlagen des Z&auml;hlens von Referenzen',
  ),
  'up' => 
  array (
    0 => 'features.gc.php',
    1 => 'Garbage Collection (Speicherbereinigung)',
  ),
  'prev' => 
  array (
    0 => 'features.gc.php',
    1 => 'Garbage Collection (Speicherbereinigung)',
  ),
  'next' => 
  array (
    0 => 'features.gc.collecting-cycles.php',
    1 => 'Sammeln zyklischer Referenzen',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'de',
    'path' => 'features/gc.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="features.gc.refcounting-basics" class="sect1">
   <h2 class="title">Grundlagen des Zählens von Referenzen</h2>
   <p class="para">
    Eine PHP-Variable wird in einem Container namens &quot;zval&quot; gespeichert. Ein
    zval-Container enthält neben dem Typ und dem Wert der Variablen noch zwei
    weitere Informationen. Die erste heißt &quot;is_ref&quot; und ist ein boolescher
    Wert, der angibt, ob die Variable Teil einer &quot;Referenzmenge&quot; ist oder
    nicht. Mit diesem Bit kann die PHP-Engine zwischen normalen Variablen und
    Referenzen unterscheiden. Da PHP mit dem &amp;-Operator erzeugte
    benutzerdefinierte Referenzen zulässt, hat ein zval-Container auch einen
    internen Mechanismus zum Zählen von Referenzen, um die Speichernutzung zu
    optimieren. Diese zweite zusätzliche Information wird &quot;refcount&quot; genannt
    und enthält die Anzahl der Variablennamen (auch Symbole genannt), die auf
    diesen einen zval-Container verweisen. Alle Symbole sind in einer
    Symboltabelle gespeichert, von denen es eine pro Bereich gibt. Es gibt
    einen Bereich für das Hauptskript (d. h. das vom Browser angeforderte),
    sowie einen für jede Funktion oder Methode.
   </p>
   <p class="para">
    Ein zval-Container wird erstellt, wenn eine neue Variable mit einem
    konstanten Wert erstellt wird, z. B.:
    <div class="example" id="example-1">
     <p><strong>Beispiel #1 Erstellen eines neuen zval-Containers</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= </span><span style="color: #DD0000">"new string"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
   <p class="para">
    In diesem Fall wird der neue Symbolname <code class="literal">a</code> im aktuellen
    Bereich erstellt und ein neuer Variablencontainer mit dem Typ
    <span class="type"><a href="language.types.string.php" class="type string">string</a></span> und dem Wert <code class="literal">new string</code> angelegt.
    Das Bit &quot;is_ref&quot; ist standardmäßig auf <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong> gesetzt, weil noch keine
    benutzerdefinierte Referenz erstellt wurde. Der &quot;refcount&quot; ist auf
    <code class="literal">1</code> gesetzt, da es nur ein Symbol gibt, das diesen
    Variablencontainer verwendet. Es ist zu beachten, dass Referenzen (d. h.
    &quot;is_ref&quot; ist <strong><code><a href="reserved.constants.php#constant.true">true</a></code></strong>) mit &quot;refcount&quot; <code class="literal">1</code> so behandelt
    werden, als ob sie keine Referenzen wären (d. h. als ob &quot;is_ref&quot; <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong>
    wäre). Wenn <a href="http://xdebug.org/" class="link external">&raquo;&nbsp;Xdebug</a> installiert ist,
    kann <span class="function"><strong>xdebug_debug_zval()</strong></span> aufgerufen werden, um diese
    Informationen anzuzeigen.
   </p>
   <p class="para">
    <div class="example" id="example-2">
     <p><strong>Beispiel #2 Anzeigen von zval-Informationen</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= </span><span style="color: #DD0000">"new string"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">(</span><span style="color: #DD0000">'a'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt folgende Ausgabe:</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=1, is_ref=0)=&#039;new string&#039;
</pre></div>
     </div>
    </div>
   </p>
   <p class="para">
    Wenn diese Variable einem anderen Variablennamen zugewiesen wird, erhöht
    sich der Referenzzähler.
   </p>
   <p class="para">
    <div class="example" id="example-3">
     <p><strong>Beispiel #3 Erhöhen des Referenzzählers eines Zval</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= </span><span style="color: #DD0000">"new string"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$b </span><span style="color: #007700">= </span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt folgende Ausgabe:</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=2, is_ref=0)=&#039;new string&#039;
</pre></div>
     </div>
    </div>
   </p>
   <p class="para">
    Der Referenzzähler ist hier <code class="literal">2</code>, weil derselbe
    Variablencontainer sowohl mit <var class="varname">a</var> als auch mit
    <var class="varname">b</var> verknüpft ist. PHP ist schlau genug, den eigentlichen
    Variablencontainer nicht zu kopieren, wenn es nicht notwendig ist.
    Variablencontainer werden zerstört, wenn der &quot;refcount&quot; Null erreicht. Der
    &quot;refcount&quot; wird um eins verringert, wenn ein Symbol, das mit dem
    Variablencontainer verbunden ist, den Gültigkeitsbereich verlässt (z. B. am
    Ende einer Funktion) oder wenn ein Symbol nicht mehr zugewiesen ist (z. B.
    durch den Aufruf von <span class="function"><a href="function.unset.php" class="function">unset()</a></span>). Das folgende Beispiel
    zeigt dies:
   </p>
   <p class="para">
    <div class="example" id="example-4">
     <p><strong>Beispiel #4 Verringern des zval-Referenzzählers</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= </span><span style="color: #DD0000">"new string"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$c </span><span style="color: #007700">= </span><span style="color: #0000BB">$b </span><span style="color: #007700">= </span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$b </span><span style="color: #007700">= </span><span style="color: #0000BB">42</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br />unset( </span><span style="color: #0000BB">$c </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt folgende Ausgabe:</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=3, is_ref=0)=&#039;new string&#039;
a: (refcount=2, is_ref=0)=&#039;new string&#039;
a: (refcount=1, is_ref=0)=&#039;new string&#039;
</pre></div>
     </div>
    </div>
   </p>
   <p class="para">
    Wenn nun <code class="literal">unset($a);</code> aufgerufen wird, wird der
    Variablencontainer einschließlich Typ und Wert aus dem Speicher entfernt.
   </p>

   <div class="sect2" id="features.gc.compound-types">
    <h3 class="title">Zusammengesetzte Typen</h3>

    <p class="para">
     Etwas komplexer wird es bei zusammengesetzten Typen wie
     <span class="type"><a href="language.types.array.php" class="type Array">Array</a></span>s und <span class="type">Objekt</span>en. Im Gegensatz zu
     <span class="type">scalar</span>en Werten speichern <span class="type"><a href="language.types.array.php" class="type Array">Array</a></span>s und
     <span class="type">Objekt</span>e ihre Eigenschaften in einer eigenen Symboltabelle.
     Das bedeutet, dass das folgende Beispiel drei zval-Container erzeugt:
    </p>
    <p class="para">
     <div class="example" id="example-5">
      <p><strong>Beispiel #5 Erstellen eines <span class="type"><a href="language.types.array.php" class="type Array">Array</a></span>-Zvals</strong></p>
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= array( </span><span style="color: #DD0000">'meaning' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'life'</span><span style="color: #007700">, </span><span style="color: #DD0000">'number' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">42 </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
      </div>

      <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt
eine ähnliche Ausgabe wie:</p></div>
      <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=1, is_ref=0)=array (
   &#039;meaning&#039; =&gt; (refcount=1, is_ref=0)=&#039;life&#039;,
   &#039;number&#039; =&gt; (refcount=1, is_ref=0)=42
)
</pre></div>
      </div>
      <div class="example-contents"><p>Oder grafisch</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-simple-array.png" alt="Zvals für ein einfaches Array" width="593" height="143" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     Die drei zval-Container sind: <var class="varname">a</var>,
     <var class="varname">meaning</var> und <var class="varname">number</var>. Ähnliche
     Regeln gelten für das Erhöhen und Verringern von &quot;refcounts&quot;. Im
     Folgenden fügen wir dem Array ein weiteres Element hinzu und setzen
     seinen Wert auf den Inhalt eines bereits vorhandenen Elements:
    </p>
    <p class="para">
     <div class="example" id="example-6">
      <p><strong>Beispiel #6 Hinzufügen eines bereits vorhandenen Elements zu einem Array</strong></p>
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= array( </span><span style="color: #DD0000">'meaning' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'life'</span><span style="color: #007700">, </span><span style="color: #DD0000">'number' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">42 </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">'life'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">'meaning'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
      </div>

      <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt
eine ähnliche Ausgabe wie:</p></div>
      <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=1, is_ref=0)=array (
   &#039;meaning&#039; =&gt; (refcount=2, is_ref=0)=&#039;life&#039;,
   &#039;number&#039; =&gt; (refcount=1, is_ref=0)=42,
   &#039;life&#039; =&gt; (refcount=2, is_ref=0)=&#039;life&#039;
)
</pre></div>
      </div>
      <div class="example-contents"><p>Oder grafisch</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-simple-array2.png" alt="Zvals für ein einfaches Array mit einer Referenz" width="593" height="143" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     Aus der obigen Xdebug-Ausgabe geht hervor, dass sowohl das alte als auch
     das neue Array-Element nun auf einen zval-Container zeigen, dessen
     &quot;refcount&quot; <code class="literal">2</code> ist. Obwohl die Xdebug-Ausgabe zwei
     zval-Container mit dem Wert <code class="literal">&#039;life&#039;</code> anzeigt, handelt es
     sich um denselben. Die Funktion <span class="function"><strong>xdebug_debug_zval()</strong></span>
     zeigt dies nicht an, aber man könnte es sehen, wenn man sich auch den
     Speicherzeiger anzeigen lässt.
    </p>
    <p class="para">
     Wenn ein Element aus dem Array entfernt wird, ist das so, als würde ein
     Symbol aus einem Bereich entfernt. Dadurch wird der &quot;refcount&quot; eines
     Containers, auf den ein Array-Element zeigt, verringert. Auch hier gilt:
     Wenn der &quot;refcount&quot; Null erreicht, wird der Variablencontainer aus dem
     Speicher entfernt. Ein weiteres Beispiel soll dies verdeutlichen:
    </p>
    <p class="para">
     <div class="example" id="example-7">
      <p><strong>Beispiel #7 Entfernen eines Elements aus einem Array</strong></p>
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= array( </span><span style="color: #DD0000">'meaning' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'life'</span><span style="color: #007700">, </span><span style="color: #DD0000">'number' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">42 </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">'life'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">'meaning'</span><span style="color: #007700">];<br />unset( </span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">'meaning'</span><span style="color: #007700">], </span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">'number'</span><span style="color: #007700">] );<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
      </div>

      <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt
eine ähnliche Ausgabe wie:</p></div>
      <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=1, is_ref=0)=array (
   &#039;life&#039; =&gt; (refcount=1, is_ref=0)=&#039;life&#039;
)
</pre></div>
      </div>
     </div>
    </p>
    <p class="para">
     Interessant wird es nun, wenn das Array selbst als Element des Arrays
     hinzugefügt wird. Das geschieht im nächsten Beispiel, in dem außerdem ein
     Referenzoperator eingebaut wird, da PHP sonst eine Kopie erstellen würde:
    </p>
    <p class="para">
     <div class="example" id="example-8">
      <p><strong>Beispiel #8 Hinzufügen des Arrays als Element von sich selbst</strong></p>
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$a </span><span style="color: #007700">= array( </span><span style="color: #DD0000">'one' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">[] =&amp; </span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">xdebug_debug_zval</span><span style="color: #007700">( </span><span style="color: #DD0000">'a' </span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
      </div>

      <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt
eine ähnliche Ausgabe wie:</p></div>
      <div class="example-contents screen">
<div class="cdata"><pre>
a: (refcount=2, is_ref=1)=array (
   0 =&gt; (refcount=1, is_ref=0)=&#039;one&#039;,
   1 =&gt; (refcount=2, is_ref=1)=...
)
</pre></div>
      </div>
      <div class="example-contents"><p>Oder grafisch</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-loop-array.png" alt="Zvals bei einem Array mit zyklischer Referenz" width="533" height="144" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     Wie man sieht, zeigen nun sowohl die Array-Variable
     (<var class="varname">a</var>) als auch das zweite Element (<var class="varname">1</var>)
     auf einen Variablencontainer, der einen &quot;refcount&quot; von
     <code class="literal">2</code> hat. Das &quot;...&quot; in der obigen Darstellung zeigt, dass
     es sich um eine Rekursion handelt, was natürlich in diesem Fall bedeutet,
     dass das &quot;...&quot; zurück auf das ursprüngliche Array zeigt.
    </p>
    <p class="para">
     Genau wie zuvor wird beim Aufheben einer Variablen das Symbol entfernt,
     und die Anzahl der Referenzen des Variablencontainers, auf den sie zeigt,
     wird um eins verringert. Wenn also die Variable <var class="varname">$a</var>
     nach der Ausführung des obigen Codes aufgehoben wird, wird die Anzahl der
     Referenzen des Variablencontainers, auf den <var class="varname">$a</var> und das
     Element &quot;1&quot; zeigen, um eins verringert, von &quot;2&quot; auf &quot;1&quot;. Dies kann wie
     folgt dargestellt werden:
    </p>
    <p class="para">
     <div class="example" id="example-9">
      <p><strong>Beispiel #9 Aufheben von <var class="varname">$a</var></strong></p>
      <div class="example-contents screen">
<div class="cdata"><pre>
(refcount=1, is_ref=1)=array (
   0 =&gt; (refcount=1, is_ref=0)=&#039;one&#039;,
   1 =&gt; (refcount=1, is_ref=1)=...
)
</pre></div>
      </div>
      <div class="example-contents"><p>Oder grafisch</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-leak-array.png" alt="Zvals nach dem Entfernen eines Arrays mit einer zyklischen Referenz, was das Speicherleck deutlich macht" width="463" height="144" />
       </div>
      </div>
     </div>
    </p>
   </div>

   <div class="sect2" id="features.gc.cleanup-problems">
    <h3 class="title">Probleme bei der Bereinigung</h3>
    <p class="para">
     Obwohl es in keinem Bereich mehr ein Symbol gibt, das auf diese Struktur
     zeigt, kann sie nicht bereinigt werden, weil das Array-Element &quot;1&quot; immer
     noch auf dasselbe Array zeigt. Da es kein externes Symbol gibt, das
     darauf verweist, gibt es für den Benutzer keine Möglichkeit, diese
     Struktur zu bereinigen, was zu einem Speicherleck führt. Glücklicherweise
     bereinigt PHP diese Datenstruktur am Ende der Anfrage, aber bis dahin
     nimmt sie wertvollen Speicherplatz in Anspruch. Diese Situation tritt
     häufig auf, wenn Parsing-Algorithmen oder andere Dinge implementiert
     werden, bei denen ein untergeordnetes Element auf ein &quot;übergeordnetes&quot;
     Element zurückverweist. Die gleiche Situation kann natürlich auch bei
     Objekten eintreten, wobei dies sogar wahrscheinlicher ist, da Objekte
     immer implizit
     &quot;<a href="language.oop5.references.php" class="link">per Referenz</a>&quot; verwendet
     werden.
    </p>
    <p class="para">
     Das ist vielleicht kein Problem, wenn es nur ein- oder zweimal vorkommt,
     aber wenn es Tausende oder sogar Millionen solcher Speicherverluste gibt,
     fängt es natürlich an, zum Problem zu werden. Besonders problematisch ist
     dies bei lang laufenden Skripten, z. B. Daemons, bei denen die Anfrage im
     Grunde nie endet, oder bei großen Mengen von Unit-Tests. Letzteres führte
     zu Problemen bei der Ausführung der Unit-Tests für die
     Template-Komponente der eZ Components-Bibliothek. In einigen Fällen
     wurden über 2 GB Speicher benötigt, die der Testserver nicht zur
     Verfügung hatte.
    </p>
   </div>
  </div><?php manual_footer($setup); ?>