PHP垃圾回收机制

WBOY
Freigeben: 2016-06-06 20:44:10
Original
993 Leute haben es durchsucht

PHP5.2版本的垃圾回收机制主要针对zval结构中的refcount=0时释放变量,但复合类型的数组或对象,环形引用或者引用自己,都是造成内存泄露,PHP官网的介绍5.3的GC机制,通过将zval放入root buffer,进行模拟删除(refcount-1),当refcount==0时被认为是垃圾,而回收,下面是4个步骤:
PHP垃圾回收机制

例如:

<code class="lang-php"><?php $a = array('one');
$a[] = &$a;
?>
</code>
Nach dem Login kopieren
Nach dem Login kopieren

这样$a数组就有两个元素,一个索引为0,值为字符one,另外一个索引为1,为$a自身的引用,内部存储如下:
a: (refcount=2, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=2, is_ref=1)=...
)
“...”表示1指向a自身,是一个环形引用:
PHP垃圾回收机制

按照网上表达所说:先放入root buffer中,refcount-1,这时$a的refcount=1,然后unset一下,refcount=0,则认为$a为垃圾
问题:
1. 我现在假设$a数组中,有2个key引用了自己,比如:

<code class="lang-php"><?php $a = array('one');
$a[] = &$a;
$a[] = &$a;
?>
</code>
Nach dem Login kopieren
Nach dem Login kopieren

a: (refcount=3, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=3, is_ref=1)=...
2 => (refcount=3, is_ref=1)=...
)
那么该数组进行unset后肯定是个垃圾,那么比如我先放到buffer, refcount-1,那么refcount=2,然后再unset-1,refcount=1,这样似乎虽然这个数组删除时会造成垃圾,但根据新的GC的机制说,只有当refcount=0时才会被认为是垃圾,那不是矛盾了吗? 那我数组里面是不是只要>=2的key引用了本身,都不会视为垃圾了?

回复内容:

PHP5.2版本的垃圾回收机制主要针对zval结构中的refcount=0时释放变量,但复合类型的数组或对象,环形引用或者引用自己,都是造成内存泄露,PHP官网的介绍5.3的GC机制,通过将zval放入root buffer,进行模拟删除(refcount-1),当refcount==0时被认为是垃圾,而回收,下面是4个步骤:
PHP垃圾回收机制

例如:

<code class="lang-php"><?php $a = array('one');
$a[] = &$a;
?>
</code>
Nach dem Login kopieren
Nach dem Login kopieren

这样$a数组就有两个元素,一个索引为0,值为字符one,另外一个索引为1,为$a自身的引用,内部存储如下:
a: (refcount=2, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=2, is_ref=1)=...
)
“...”表示1指向a自身,是一个环形引用:
PHP垃圾回收机制

按照网上表达所说:先放入root buffer中,refcount-1,这时$a的refcount=1,然后unset一下,refcount=0,则认为$a为垃圾
问题:
1. 我现在假设$a数组中,有2个key引用了自己,比如:

<code class="lang-php"><?php $a = array('one');
$a[] = &$a;
$a[] = &$a;
?>
</code>
Nach dem Login kopieren
Nach dem Login kopieren

a: (refcount=3, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=3, is_ref=1)=...
2 => (refcount=3, is_ref=1)=...
)
那么该数组进行unset后肯定是个垃圾,那么比如我先放到buffer, refcount-1,那么refcount=2,然后再unset-1,refcount=1,这样似乎虽然这个数组删除时会造成垃圾,但根据新的GC的机制说,只有当refcount=0时才会被认为是垃圾,那不是矛盾了吗? 那我数组里面是不是只要>=2的key引用了本身,都不会视为垃圾了?

找到答案了吗?我尝试回答下

按照楼主说的,看看下面的内容:

<code class="php">$a = 123;
$b = $a;   //a: (refcount=2, is_ref=0)=123   b: (refcount=2, is_ref=0)=123
unset($b);    //a: (refcount=1, is_ref=0)=123</code>
Nach dem Login kopieren

此时a所指向的zval也会进入垃圾周期,然后对refcount减一,是不是符号a指向的zval也要删除了?显然不是

这里根据我所了解的说说我的看法:GC不会对可能的垃圾根元素进行减一操作,而是会对根元素下面的元素进行减一操作,这样解释才合理。
就说说你这种情况,根节点zval计数不会进行减一操作,循环引用的时候,对循环引用指向的zval计数进行减一,这样不管多少循环引用都可以减到0,这样是不是可以说的通了。

仔细看图你没发现问题么?明明产生了一个自引用,但是为什么refcount还是1呢?应该是变量释放到buffer里面然后refcount--的原因。你就是这块没理解对。

Verwandte Etiketten:
php
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage