普通的引用变量的销毁大家都知道, 当unset的时候如果refcount = 0 则认为无用, 销毁。
但是手册中提到一点会有递归引用的问题,很是奇葩
代码如下
<?php $a = 1; $arr[0] = &$a; $arr[1] = &$arr; /* 用print_r打印出现 Array ( [0] => 1 [1] => Array ( [0] => 1 [1] => Array *RECURSION* ) ) */
这个时候 $arr[1] 递归的引用了$arr , 虽然没有意义,但是按照原来的判断refcount为0的方式会出现问题,因为当unset($arr)时, refcount=1 ,此时$arr成为一个没有任何变量指向的垃圾数据。
手册中提到的方法是
当一个变量出现refcount引用计数减少到非零值时, 这个变量就进去了垃圾回收缓冲区
缓冲区定时进行数据清理
步骤如下
深度优先遍历每个结点,被遍历的结点被标记为已经遍历,第二次遍历到将不会再进行操作, 遍历处理操作是将refcount-- , 如果遍历结束时 refcount=0 则认为是垃圾数据,则回收, 如果refcount>0 则 refcount+=1
此处疑问出来了,这种方式明显有缺陷
比如
1. 对于 $a = 1; $b =&$a; 然后unset($b); 此时$a进入垃圾回收周期, 被遍历,并且refcount--后refcount=0 被回收, 但是$a此时还有用啊。这种情况属于有用的资源被误回收
2. $a = 1; $arr = arrary(); $arr[0] = &$a; $arr[1] = &$arr; $arr[2] = &$arr; unset($arr); 此处有两处引用 , 但是处理的时候如果遍历并且refcount--之后再次遍历不再进行refcount--操作,所以 $arr这种垃圾是没法回收的
官方手册的地址如下, 不知道是不是被我曲解了, http://www.php.net/manual/zh/features.gc.collecting-cycles.php