Циклические ссылки в PHP 7.4

В PHP 7.4 я заметил количество собранных циклов, возвращаемое gc_collect_cycles всегда равен нулю, если в циклическом объекте, на который ссылаются, есть метод destructor.

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 отключен?


person Rain    schedule 10.12.2019    source источник


Ответы (1)


Начиная с PHP 7.4, первоначальный запуск сборки мусора будет вызывать деструкторы только тех объектов, у которых они есть, а фактическое уничтожение объекта откладывается до следующего запуска сборки мусора. Вы можете увидеть это, если выполните два вызова gc_collect_cycles(): https://3v4l.org/0LIVn

Причина такого поведения в том, что деструкторы могут вводить дополнительные ссылки на объект, так что его больше нельзя уничтожить. Предыдущие версии использовали ненадежную эвристику для обнаружения этого случая. Вместо этого PHP 7.4 откладывает уничтожение до отдельного запуска сборщика мусора.

person NikiC    schedule 10.12.2019