<?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 => 'pt_BR',
  ),
  'this' => 
  array (
    0 => 'features.gc.refcounting-basics.php',
    1 => 'B&aacute;sico sobre Contagem de Refer&ecirc;ncia',
    2 => 'B&aacute;sico sobre Contagem de Refer&ecirc;ncia',
  ),
  'up' => 
  array (
    0 => 'features.gc.php',
    1 => 'Coletor de Lixo',
  ),
  'prev' => 
  array (
    0 => 'features.gc.php',
    1 => 'Coletor de Lixo',
  ),
  'next' => 
  array (
    0 => 'features.gc.collecting-cycles.php',
    1 => 'Ciclos de Coleta',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'pt_BR',
    '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">Básico sobre Contagem de Referência</h2>
   <p class="para">
    Uma variável PHP é armazenada em um contêiner chamado &quot;zval&quot;. Um zval
    contém, além do tipo e do valor da variável, dois bits adicionais de
    informação. O primeiro é chamado de &quot;is_ref&quot; e é um valor booleano
    que indica se a variável é parte de um &quot;conjunto de referência&quot; ou não. Com
    este bit, o motor do PHP sabe como diferenciar variáveis normais
    de referências. Como o PHP permite referências no nível do usuário, como as criadas pelo
    operador &amp;, um contêiner zval também tem um mecanismo de contagem de referência
    interno para otimizar o uso de memória. Esta segunda parte de informação
    adicional, chamado &quot;refcount&quot;, contém a quantidade de nomes de variáveis (também
    chamadas de símbolos) que apontam para este contêiner. Todos os símbolos são armazenados em
    uma tabela de símbolos, e existe uma por escopo. Existe um escopo para o
    script principal (ou seja, aquele requisitado através do navegador), assim como um escopo
    para cada função ou método.
   </p>
   <p class="para">
    Um contêiner zval é criado quando uma nova variável é criada com um valor
    constante, como em:
    <div class="example" id="example-1">
     <p><strong>Exemplo #1 Criando um novo contêiner 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">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
   <p class="para">
    Neste caso, o nome do símbolo, <code class="literal">a</code>, é criado no escopo atual,
    e um novo contêiner de variável é criado com o tipo <span class="type"><a href="language.types.string.php" class="type string">string</a></span> e o valor
    <code class="literal">new string</code>. O bit &quot;is_ref&quot; é por padrão definido para <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong> porque nenhuma
    referência no nível do usuário foi criada. O &quot;refcount&quot; é definido para <code class="literal">1</code> já
    que existe apenas um símbolo que faz uso deste contêiner de variável. Note
    que referências (isto é, &quot;is_ref&quot; igual a <strong><code><a href="reserved.constants.php#constant.true">true</a></code></strong>) com &quot;refcount&quot; igual a <code class="literal">1</code>, são
    tratadas como se elas não fossem referências (como se &quot;is_ref&quot; fosse <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong>). Se o <a href="http://xdebug.org/" class="link external">&raquo;&nbsp;Xdebug</a> estiver instalado, esta informação pode ser
    mostrada chamando-se a função <span class="function"><strong>xdebug_debug_zval()</strong></span>.
   </p>
   <p class="para">
    <div class="example" id="example-2">
     <p><strong>Exemplo #2 Mostrando a informação 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">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>O exemplo acima produzirá:</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">
    Atribuir esta variável a outro nome de variável irá aumentar o &quot;refcount&quot;.
   </p>
   <p class="para">
    <div class="example" id="example-3">
     <p><strong>Exemplo #3 Aumentando o &quot;refcount&quot; de um 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>O exemplo acima produzirá:</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">
    O refcount é <code class="literal">2</code> aqui, porque o mesmo contêiner de variável está ligado
    tanto com <var class="varname">a</var> quanto com <var class="varname">b</var>.
    O PHP é inteligente o suficiente para não copiar o contêiner real da
    variável quando não for necessário. Contêineres são destruídos quando
    o &quot;refcount&quot; atinge zero. O &quot;refcount&quot; é diminuído em uma unidade quando qualquer
    símbolo ligado ao contêiner da variável deixa o escopo (ex.: quando a
    função termina) ou quando um símbolo perde a atribuição (ex.: chamando <span class="function"><a href="function.unset.php" class="function">unset()</a></span>).
    O exemplo a seguir mostra isso:
   </p>
   <p class="para">
    <div class="example" id="example-4">
     <p><strong>Exemplo #4 Diminuindo o &quot;refcount&quot; de 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">$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>O exemplo acima produzirá:</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">
    Se agora <code class="literal">unset($a);</code> for chamada, o contêiner da variável, incluindo o tipo
    e o valor, serão removidos da memória.
   </p>

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

    <p class="para">
     As coisas ficam um pouco mais complexas com tipos compostos como <span class="type"><a href="language.types.array.php" class="type array">array</a></span>s e
     <span class="type"><a href="language.types.object.php" class="type object">object</a></span>s. Ao contrário dos valores e<span class="type">scalar</span>es, <span class="type"><a href="language.types.array.php" class="type array">array</a></span>s
     e <span class="type"><a href="language.types.object.php" class="type object">object</a></span>s armazenam suas
     propriedades em uma tabela de símbolos própria. Isto significa que o exemplo
     a seguir cria três contêineres zval:
    </p>
    <p class="para">
     <div class="example" id="example-5">
      <p><strong>Exemplo #5 Criando um zval de <span class="type"><a href="language.types.array.php" class="type array">array</a></span></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>O exemplo acima produzirá
algo semelhante a:</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>Ou graficamente</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-simple-array.png" alt="Zvals para um array simples" width="593" height="143" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     Os três contêineres zval são: <var class="varname">a</var>, <var class="varname">meaning</var>, e <var class="varname">number</var>.
     Regras similares se aplicam para aumento e redução de &quot;refcounts&quot;. Abaixo, outro elemento é
     adicionado ao array, e define seu valor ao conteúdo de um elemento
     já existente:
    </p>
    <p class="para">
     <div class="example" id="example-6">
      <p><strong>Exemplo #6 Adicionando elemento já existente a um 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>O exemplo acima produzirá
algo semelhante a:</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>Ou graficamente</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-simple-array2.png" alt="Zvals para um array simples com uma referência" width="593" height="143" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     Pela saída do Xdebug acima, pode-se perceber que tanto o elemento antigo do array
     quanto o novo agora apontam para um contêiner zval cujo &quot;refcount&quot; é
     <code class="literal">2</code>. Embora a saída do Xdebug mostre dois contêineres zval
     com valor <code class="literal">&#039;life&#039;</code>, eles são o mesmo. A função
     <span class="function"><strong>xdebug_debug_zval()</strong></span> não mostra isso, mas
     pode-se ver isso mostrando o ponteiro de memória.
    </p>
    <p class="para">
     Remover o elemento de um array é como remover um símbolo de um escopo.
     Fazendo isso, o &quot;refcount&quot; de um contêiner ao qual um elemento do array aponta
     é reduzido. Novamente, quando o &quot;refcount&quot; atinge zero, o contêiner da
     variável é removido da memória. Um exemplo para mostrar isto:
    </p>
    <p class="para">
     <div class="example" id="example-7">
      <p><strong>Exemplo #7 Removendo um elemento de um 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>O exemplo acima produzirá
algo semelhante a:</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">
     Agora, as coisas ficam interessantes se o próprio array for adicionado como
     um elemento do array, o que é mostrado no exemplo a seguir, onde também um operador
     de referência foi inserido, senão o PHP criaria uma cópia:
    </p>
    <p class="para">
     <div class="example" id="example-8">
      <p><strong>Exemplo #8 Adicionando o próprio array como um elemento de si mesmo</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>O exemplo acima produzirá
algo semelhante a:</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>Ou graficamente</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-loop-array.png" alt="Zvals para um array com referência circular" width="533" height="144" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     Pode-se perceber que a variável do array (<var class="varname">a</var>) assim como o segundo elemento
     (<var class="varname">1</var>) agora apontam para um contêiner de variável que tem um &quot;refcount&quot; de <code class="literal">2</code>.
     Os &quot;...&quot; no exemplo acima mostram que há recursão envolvida, e que,
     obviamente, neste caso significa que os &quot;...&quot; apontam de volta ao
     array original.
    </p>
    <p class="para">
     Como antes, tirar a atribuição de uma variável remove o símbolo, e a
     contagem de referência do contêiner da variável à qual o símbolo aponta é reduzida em uma
     unidade. Então, se a variável <var class="varname">$a</var> perder a atribuição após execução do código acima,
     a contagem de referência do contêiner da variável à qual <var class="varname">$a</var> e o elemento &quot;1&quot; apontam
     será diminuída em uma unidade, de &quot;2&quot; para &quot;1&quot;. Isto pode ser representado assim:
    </p>
    <p class="para">
     <div class="example" id="example-9">
      <p><strong>Exemplo #9 Removendo a atribuição de <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>Ou graficamente</p></div>
      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-leak-array.png" alt="Zvals depois da remoção do array com um referência circular demonstrando o vazamento de memória" width="463" height="144" />
       </div>
      </div>
     </div>
    </p>
   </div>

   <div class="sect2" id="features.gc.cleanup-problems">
    <h3 class="title">Problemas na Limpeza</h3>
    <p class="para">
     Embora não haja mais um símbolo em nenhum escopo apontando para esta
     estrutura, ela não pode ser limpa porque o elemento &quot;1&quot; do array ainda
     aponta para este mesmo array. Como não há símbolo externo apontando para
     ela, não há como um usuário limpar esta estrutura; e aí acontece o
     vazamento de memória. Felizmente, o PHP irá limpar esta estrutura de dados no final
     da requisição, mas até lá, ela irá ocupar um espaço valioso na
     memória. Esta situação ocorre frequentemente quando se está implementando algoritmos
     de interpretação ou outros onde existe um elemento &quot;filho&quot; apontando de volta para um
     elemento &quot;pai&quot;. A mesma situação também pode com certeza ocorrer com objetos, onde
     na verdade existe mais probabilidade de ocorrer, já que objetos são sempre implicitamente
     usados &quot;<a href="language.oop5.references.php" class="link">por referência</a>&quot;.
    </p>
    <p class="para">
     Isso pode não ser um problema quanto acontecer somente uma ou duas vezes, mas se
     houver milhares, ou até milhões dessas perdas de memória, obviamente
     começa a ser um problema. É especialmente problemático em scripts de execução
     longa, como daemons onde a requisição basicamente nunca termina,
     ou em grandes conjuntos de testes de unidades. Este último já causou problemas durante
     a execução de testes de unidades para o componente Template da bilioteca eZ
     Components. Em alguns casos, era necessário mais de 2GB de memória, que o servidor
     de testes não tinha.
    </p>
   </div>
  </div><?php manual_footer($setup); ?>