Проблема циклических ссылок

Все дело в злополучных счетчиках ссылок. Смотрите: $father ссылается на $child, а $child - на $father. Это значит, что и у того, и у другого счетчик равен 1 (ведь на каждого из них ссылается другой)! Стоит ли удивляться, что сборщик мусора не сработал?.. Ведь в программе не осталось ни одного объекта с нулевым счетчиком ссылок.

ПРИМЕЧАНИЕ

Аналогия с гардеробом: вы сдаете в него свое пальто, а также чужое (которое взяли только что, например, по поддельному номерку). При этом (для конспирации) номерок от своего пальто вы кладете в карман чужого, а от чужого - в карман своего. Проделав данную махинацию, вы обнаружите, что не можете больше получить одежду!

Мы рассмотрели пример циклических ссылок с "длиной цикла", равной двум. Однако, конечно, РНР попадает в безвыходную ситуацию и в случае большей косвенности: А ссылается на В, В ссылается на С, С ссылается на А.

ПРИМЕЧАНИЕ

Еще одна аналогия - известная безвыходная ситуация "ключи от машины в квартире, ключи от квартиры в сейфе, ключи от сейфа - в машине".

Еще более примечателен по своей простоте следующий код:

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

Итак, общий вывод: алгоритм сборки мусора и автоматического вызова деструкторов попросту "не срабатывает", когда в программе имеются кольцевые ссылки.

Проблема утечки памяти в результате циклических ссылок была неразрешима до версии РНР 5.3, начиная с которой в сборщик мусора РНР внедрен синхронный механизм сбора циклических ссылок.

Вкратце, все объекты, генерирующие ссылки, помещаются в специальный буфер, который называется корневым. При заполнении буфера (а его размер составляет 10000) стартует процедура сборки мусора, в результате которой происходит обход дерева всех ссылающихся элементов, алгоритм разрешает циклы и корректирует счетчики. Объекты, чьи счетчики стали равны нулю, удаляются. Механизм довольно ресурсоемок и включается только по заполнению буфера. По умолчанию сборщик мусора включен; если ваши скрипты работают короткое время и потребляют мало памяти, можно увеличить производительность за счет отключения сборщика мусора, установив значение директивы\ zend.enable_gc в конфигурационном файле php.ini в off.



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: