php5.3版本以后的才有了所谓的新的垃圾回收机制GC,
以前是基于引用计数的方式,这里就需要提一下引用计数的知识,官方手册里面说php的每个变量都是存在一个叫做zval的容器里面,这个容器不仅包含了这个变量的值和类型,还包含了另外两个重要的信息,“is_ref”和“refcount”,“is_ref”看名字就应该知道大概和引用相关,它是一个bool值,如果这个值是true那么代表这是一个引用变量,否则是普通变量。“refcount”指的是有多少个变量(符号)指向这个zval容器
例如:
$a="test"
xdebug_debug_zval( 'a' );
a:(refcount=1, is_ref=0)= "test"
//7.0以后是做了优化,refcount 为0.只有后续使用才会加,只是测试使用
$b = $a;
a: (refcount=2,is_ref=0)= "test"
$b = $b + 1; //如果对比修改,会copy出一个容器。
a :( refcount=1,is_ref=0)="test",
b : ( refcount=1,is_ref=0)="test",
&赋值
$c=&$a
a,c:(refcount=2,is_ref=1)="test"
unset($c)
a : (refcount=1,is_ref=1)="test"
数组
$a=array("1","2"),
a: (refcount=1, is_ref=0)=array (
0 => (refcount=1, is_ref=0)='1',
1 => (refcount=1, is_ref=0)='2'
)
//$a本身指向一个zval容器存放外,它的每一个元素也都分别指向一个zval容器
$a = array( 'one' );
$a[] =& $a; //数组引用会导致出现自闭环
引用计数不为空,导致内存泄露,如果出现循环或者是递归,将导致大量的内存泄露,因此5.3之后出现php垃圾回收机制。
回收规则:
- 如果一个zval容器的refcount增加,说明有新的变量(符号)指向这个容器,那么这个容器当然不会是垃圾,它将被继续使用。
- 如果一个zval容器的refcount减少到0了,那么说明没有变量(符号)指向这个容器,它就会被php引擎销毁。
- 如果一个zval容易的refcount减少了,但是不是0,那么这个容器就有可能是垃圾,就会被垃圾回收机制所管理。
对于一个包含环形引用的数组,对数组中包含的每个元素的zval进行减1操作,之后如果发现数组自身的zval的refcount变成了0,那么可以判断这个数组是一个垃圾。