给出以下代码:
<?php
$a = [];
$a[] = &$a;
unset($a);
一行一行代码先来分析下:
第一行,$a = [];,定义$a变量为数组,这时候$a指向一个类型为7(数组)的zval,zval.u1.v.type=7,zval.value.arr指向一个zend_array结构;
第二行,$a[] = &$a;,传址赋值,此时,$a和$a[]两个的zval的type变为10(引用类型),zval.value.ref指向一个新的zend_reference结构体,其中zend_reference结构体中的引用计数为2,而zend_reference中zval是一个type为7的结构,zval.value.arr指向一个zend_array结构体,同时该zend_array结构体中arData指针指向一个bucket,而这个bucket结构体中也有一个zval,而这个bucket中的zval的类型也为10,因为$a[]现在是一个和$a指向同一个zend_reference结构体的类型;
第三步,unset($a);,这一步将$a的指向zval的类型就会被设置为0(IS_UNDEFF),zend_reference的引用计数也会减为1,但仍然大于0。这时候就会出现循环引用了。
接下来可以看下这幅图:

$a的zval类型变为0,那么之前指向zend_reference结构体的路就断了,后面就是一个环了,所以说出现了循环引用。