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

tjw*_*992 10 oop perl memory-leaks cyclic-reference

我最近问了一个关于在Perl中覆盖对象和内存管理的问题.我收到的一个答案告诉我,我最近写的脚本可能有问题.

我有一个脚本,有一些非常复杂的数据结构,有许多parent->child / child->parent关系.这也意味着有许多对象具有循环引用.根据这个答案,循环引用可以"欺骗"Perl的引用计数机制,如果没有正确处理它们会导致内存泄漏.


循环引用的示例:

       +-----------------------------------------------------+
       |                                                     |
       +-->+============+    +==========+                    |
           [ Reference ----->[ Blessed  ]                    |
$parent -->+============+    [ Hash     ]                    |
                             [          ]   +==========+     |
                             [ children --->[ Array    ]     |
                             [          ]   [          ]     |
                             +==========+   [ 0: ---------+  |
                                            [          ]  |  |
                                            +==========+  |  |
                                                          |  |
       +--------------------------------------------------+  |
       |                                                     |
       +-->+============+    +==========+                    |
           [ Reference ----->[ Blessed  ]                    |
$child --->+============+    [ Hash     ]                    |
                             [          ]                    |
                             [ parent: ----------------------+
                             [          ]
                             +==========+
Run Code Online (Sandbox Code Playgroud)

(免责声明 - 这不是我的史诗艺术品 - 感谢@Ikegami这个甜蜜的ASCII图!)

问题:每个对象都引用另一个对象...这意味着,一旦$parent$child走出去的范围,Perl的引用计数器仍然认为每个对象的引用存在,所以内存永远不会被释放.你在内存中找到了两个对象,无法访问其中任何一个的数据!


我的问题是: 处理循环引用以确保Perl正确处理其清理的正确方法是什么?当消除对自引用对象的所有外部引用时,如何确保Perl不会留下任何碎片?

Sob*_*que 12

Scalar::Util特别是weaken功能.

左值$ ref将变为弱引用.这意味着它不会在它引用的对象上保留引用计数.此外,当该对象上的引用计数达到零时,引用将设置为undef.该函数改变作为参数传递的左值并且不返回任何值.

将一个或两个参考设置为"弱",并且当锚点被破坏时,菊花链将自动解开.

  • 很酷,我会试试.我希望大约一个月前我知道这件事...我有很多提及弱化的内容! (2认同)