Как работает «неустановленная» конструкция PHP внутри?

Предисловие: я знаю, как «unset» работает в пользовательской области, но я хотел бы узнать, как он работает внутри.

Когда unset вызывается в структуре zval , он уменьшает счетчик ссылок (refcount__gc). Когда refcount__gc достигает 0, переменная больше не используется и может быть удалена. Вопрос в том, всегда ли это делается сразу, или в некоторых случаях это может быть сделано позже сборщиком мусора?

Я нашел два противоречивых заявления по этому поводу:

unset () делает то, что говорит его имя, – отключает переменную. Это не приводит к немедленному освобождению памяти. Сборщик мусора PHP будет делать это, когда он увидит припадки – по желанию, как только эти циклы процессора не будут нужны в любом случае, или еще до того, как скрипт закончится из памяти, что бы ни случилось раньше. – Ответ на Stackoverflow, в котором упоминается документация php.net за 2009 год

И наоборот:

Когда refcount попадает в ноль, zval уничтожается, и любая память, которую он держит, теперь бесплатна – Лучшее понимание коллекции мусора PHP, статья 2012 года

Итак, какой из них правильный, скажем, PHP 5.3 и PHP 5.5? Если возможно, возможно, вы можете предоставить ссылку на определение unset в исходном коде PHP. Спасибо!

TL; DR

Оба утверждения верны.

Позволь мне объяснить. (Это правда, по крайней мере, с PHP 5.0 (раньше, я не знаю). Сейчас идет phpng, что делает фундаментальные изменения, но этот принцип все еще используется.)


Циркулярный сборщик мусора

Круглый сборщик мусора просто используется для круговых ссылок. Мы имеем их обычно, когда два объекта содержат ссылки друг на друга.

Так как в этом случае refcount__gc никогда не упадет до нуля … в другом месте все еще есть ссылка, нормальная ZEND_UNSET_ * (где звездочка либо ARRAY, OBJ, либо VAR) не может ее отключить. Поэтому он должен ждать сборщика мусора.

И сборщик мусора вызывается периодически только по соображениям производительности.

Определения php-src

Вы запросили определение ZEND_UNSET_VAR? http://lxr.php.net/xref/PHP_5_6/Zend/zend_vm_def.h#4069

И вот основная функция для декрементации refcount и т. Д .: http://lxr.php.net/xref/PHP_5_6/Zend/zend_execute.h#74

Какой из них правильный?

Итак, если refcount равен нулю, мы уверены, что с ним ничего не связано, и мы можем его освободить. (Второй оператор: просто говорит об отказе == 0)

Но, если это не ноль, мы помечаем переменную, которая будет проверена круговым сборщиком мусора позже. (Первое утверждение: не обязательно сразу освобождается)