11

最近、Perl でのオブジェクトの上書きとメモリ管理について質問しました。受け取った回答の 1 つで、最近書いたスクリプトに問題がある可能性があると通知されました。

parent->child / child->parent多くの関係を持つ非常に複雑なデータ構造を持つスクリプトがあります。これは、循環参照を持つオブジェクトが多いことも意味します。この回答によると、循環参照は Perl の参照カウント メカニズムを「騙し」、適切に処理しないとメモリ リークを引き起こす可能性があります。


循環参照の例:

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

(免責事項 -- これは私の壮大なアートワークではありません -- @Ikegami さん、この素敵な ASCII 図をありがとうございます! )

問題:各オブジェクトが他のオブジェクトへの参照を持っています。. . これは、いったんスコープ外$parent$child出ても、Perl の参照カウンターは各オブジェクトへの参照が存在すると考えているため、メモリが決して解放されないことを意味します。メモリ内に 2 つのオブジェクトが存在することになり、どちらのデータにもアクセスできなくなります。


私の質問は次のとおりです: Perl がそのクリーンアップを適切に処理することを保証するために、循環参照を処理する適切な方法は何ですか? 自己参照オブジェクトへのすべての外部参照が削除されたときに、Perl が一切の断片を残さないようにするにはどうすればよいでしょうか?

4

1 に答える 1

13

Scalar::Utilそして具体的にはweaken機能。

左辺値 $ref は弱い参照に変わります。これは、参照するオブジェクトの参照カウントを保持しないことを意味します。また、そのオブジェクトの参照カウントがゼロに達すると、参照は undef に設定されます。この関数は、引数として渡された左辺値を変更し、値を返しません。

リファレンスの 1 つまたは両方を「弱い」に設定すると、アンカーが破壊されたときにデイジー チェーンが自動的に解けます。

于 2015-08-14T13:20:31.750 に答える