防止 Perl 中的循环引用内存泄漏

Preventing cyclic reference memory leaks in Perl

我最近问了一个 关于在 Perl 中覆盖 objects 和内存管理的问题。我收到的其中一个答复通知我,我最近编写的脚本可能有问题。

我有一个脚本,其中包含一些非常复杂的数据结构,这些数据结构具有许多 parent->child / child->parent 关系。这也意味着有很多object有循环引用。根据,循环引用可以"trick" Perl的引用计数机制,如果处理不当会导致内存泄漏。


循环引用示例:

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

(免责声明——这不是我的史诗般的艺术作品——感谢@Ikegami 提供这个可爱的 ASCII 图!)

问题: 每个 object 都有对另一个的引用。 . .这意味着一旦 $parent$child 超出范围,Perl 的引用计数器仍然认为对每个 object 的引用存在,因此内存永远不会被释放。您最终在内存中有两个 object,但无法访问其中任何一个的数据!


My question is: What is the proper way to deal with cyclic references to ensure Perl handles its cleanup properly? How do you make sure Perl doesn't leave any pieces behind when all external references to a self-referential object are eliminated?

Scalar::Util 特别是 weaken 函数。

The lvalue $ref will be turned into a weak reference. This means that it will not hold a reference count on the object it references. Also when the reference count on that object reaches zero, the reference will be set to undef. This function mutates the lvalue passed as its argument and returns no value.

将您的一个或两个参考设置为 "weak",当锚被破坏时,菊花链将自动解开。