PHP 7.4 中的循环引用

Cyclic references in PHP 7.4

在 PHP 7.4 中,我注意到当循环引用对象中有 destructor 方法时,gc_collect_cycles 返回的收集循环数始终为零。

class A {
    public function __destruct() {

    }
}
gc_disable();

$a1 = new A;
$a2 = new A;

$a1->ref = $a2;
$a2->ref = $a1;

$a1 = $a2 = NULL;

echo('removed cycles: '.gc_collect_cycles()); // Output: removed cycles: 0

当我删除 __destruct 方法时,输出为:

removed cycles: 2

您可以看到此行为从 PHP 7.4.0beta4

开始

这是怎么回事?即使 GC 被禁用,垃圾循环也会在析构函数中收集吗?

自PHP 7.4 起,初始垃圾收集运行 将只对具有析构函数的对象调用析构函数,对象的实际销毁推迟到下一次GC 运行 .如果对 gc_collect_cycles() 执行两次调用,您可以看到这一点:https://3v4l.org/0LIVn

此行为的原因是析构函数可以引入对该对象的额外引用,这样就不再有效地销毁它。以前的版本使用不可靠的启发式方法来检测这种情况。 PHP 7.4 将改为将销毁延迟到单独的 GC 运行。