Javaとは異なり、Perlはガベージコレクションに参照カウントを使用します。C ++ RAII、スマートポインター、およびJava GCについて説明している以前の質問をいくつか検索してみましたが、Perlが循環参照の問題をどのように処理するかを理解していません。
Perlのガベージコレクターが循環参照をどのように処理するかを誰かが説明できますか?プログラムで使用されなくなった循環参照メモリを再利用する方法はありますか、それともPerlはこの問題を完全に無視しますか?
Javaとは異なり、Perlはガベージコレクションに参照カウントを使用します。C ++ RAII、スマートポインター、およびJava GCについて説明している以前の質問をいくつか検索してみましたが、Perlが循環参照の問題をどのように処理するかを理解していません。
Perlのガベージコレクターが循環参照をどのように処理するかを誰かが説明できますか?プログラムで使用されなくなった循環参照メモリを再利用する方法はありますか、それともPerlはこの問題を完全に無視しますか?
プログラミングPerl第3版の私のコピーによると。、終了時に、Perl5は循環参照を再利用するために「高価なマークアンドスイープ」を実行します。循環参照は、プログラムが終了するまで再利用されないため、できるだけ避けてください。
Perl 5は、Scalar::Utilsモジュールを介して弱参照を提供します。
Perl 6は、プラグ可能なガベージコレクションスキームに移行します(基盤となるVMには複数のガベージコレクションオプションがあり、それらのオプションの動作がPerlに影響を与える可能性があります)。つまり、さまざまなガベージコレクターから選択することも、独自に実装することもできます。コピーコレクターが欲しいですか?もちろん。着色コレクターが欲しいですか?了解しました。マーク/スイープ、圧縮など?なぜだめですか?
簡単な答えは、Perl5は循環参照を自動的に処理しないということです。コードで明示的な対策を講じない限り、循環参照を含むデータ構造は、それらを作成したスレッドが停止するまで再利用されません。これは、実行速度を低下させる実行時のガベージコレクションの必要性を回避するという点で、許容できるトレードオフと見なされます。
コードが循環参照(つまり、ノードにルートへの参照が含まれているツリー)を使用してデータ構造を作成する場合は、Scalar :: Utilモジュールを使用して、ルートノードを指す参照を「弱める」必要があります。これらの弱参照は、それらが指すものの参照カウントに追加されないため、最後の外部参照がなくなると、データ構造全体が自動的に割り当て解除されます。
例:
use Scalar::Util qw(weaken);
...
my $new_node = { content => $content, root => $root_node };
weaken $new_node->{root};
push @{$root_node->{children}}, $new_node;
データ構造に新しいノードを追加するたびにこのようなコードを使用する場合、実際にカウントされるルートへの参照は、構造の外部からの参照のみです。これはまさにあなたが望むものです。次に、ルートとそのすべての子が、ルートへの最後の外部参照がなくなるとすぐに再利用されます。
プロキシオブジェクトを見てください。
Perlは、循環参照を再利用するために、場合によっては(スレッドが停止したときに)マークアンドスイープの代替GCを適用します。「すべての値は文字列である」Perlスタンザでは、真の循環参照を作成することが困難であることに注意してください。これは実行可能ですが、「通常の」Perlコードは実行可能ではありません。そのため、参照カウントはPerlでうまく機能します。