Подтвердить что ты не робот

Предотвращение утечки циклической эталонной памяти в Perl

Недавно я спросил question о перезаписи объектов и управления памятью в Perl. Один из ответов, которые я получил, уведомил меня, что у меня может возникнуть проблема с script, который я недавно написал.

У меня есть script с некоторыми очень сложными структурами данных, которые имеют много отношений parent->child / child->parent. Это также означает, что существует много объектов, которые имеют циклические ссылки. В соответствии с этим ответом циклические ссылки могут "обмануть" механизм подсчета ссылок Perl и вызвать утечку памяти, если они не обрабатываются должным образом.


Пример циклической ссылки:

       +-----------------------------------------------------+
       |                                                     |
       +-->+============+    +==========+                    |
           [ Reference ----->[ Blessed  ]                    |
$parent -->+============+    [ Hash     ]                    |
                             [          ]   +==========+     |
                             [ children --->[ Array    ]     |
                             [          ]   [          ]     |
                             +==========+   [ 0: ---------+  |
                                            [          ]  |  |
                                            +==========+  |  |
                                                          |  |
       +--------------------------------------------------+  |
       |                                                     |
       +-->+============+    +==========+                    |
           [ Reference ----->[ Blessed  ]                    |
$child --->+============+    [ Hash     ]                    |
                             [          ]                    |
                             [ parent: ----------------------+
                             [          ]
                             +==========+

(Отказ от ответственности - это не мое эпическое произведение - спасибо @Ikegami за эту сладкую диаграмму ASCII!)

Проблема: Каждый объект имеет ссылку на другую., это означает, что после того, как $parent и $child исчезнут из области видимости, счетчик ссылок Perl все еще считает, что ссылка на каждый объект существует, поэтому память никогда не освобождается. Вы завершаете работу с двумя объектами в памяти, чтобы не получить доступ к данным ни одного из них!


Мой вопрос: Каков правильный способ обработки циклических ссылок, чтобы Perl правильно обрабатывал его очистку? Как вы убеждаетесь, что Perl не оставляет никаких деталей, когда устраняются все внешние ссылки на самореферентный объект?

4b9b3361

Ответ 1

Scalar::Util и, в частности, функцию weaken.

lvalue $ref будет переведен в слабую ссылку. Это означает, что он не будет содержать счетчик ссылок на объект, который он ссылается. Также, когда счетчик ссылок на этот объект достигнет нуля, ссылка будет установлена ​​на undef. Эта функция мутирует значение lvalue, переданное как его аргумент, и не возвращает значения.

Настройте один или оба из ваших ссылок как "слабый", а цепочка маргаритов автоматически раскроется, когда анкеры будут разрушены.