代码之家  ›  专栏  ›  技术社区  ›  tjwrona1992

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

  •  11
  • tjwrona1992  · 技术社区  · 9 年前

    我最近问了一个 question 关于用Perl重写对象和内存管理。我收到的一个回答告诉我,我可能对我最近写的剧本有问题。

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


    循环引用示例:

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

    ( 免责声明——这不是我的史诗作品——感谢@Ikegami提供的这张漂亮的ASCII图! )

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


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

    1 回复  |  直到 8 年前
        1
  •  13
  •   Sobrique    9 年前

    Scalar::Util 特别是 weaken 作用

    左值$ref将变为弱引用。这意味着它不会对其引用的对象保持引用计数。此外,当该对象上的引用计数达到零时,引用将设置为undef。此函数对作为其参数传递的左值进行变异,不返回任何值。

    将一个或两个引用设置为“弱”,当锚被破坏时,菊花链将自动解开。