gist落ちてるのでここにメモ。
package DONE1; sub DESTROY{ warn 'd1:', shift; } package DONE2; sub DESTROY{ warn 'd2:', shift; } package DONE3; sub DESTROY{ warn 'd3:', shift; } package DONE4; sub DESTROY{ warn 'd4:', shift; } package DONE5; sub DESTROY{ warn 'd5:', shift; } package main; use strict; use warnings; use Scalar::Util; my ($inner, $outer); { my $d1 = bless {}, 'DONE1'; my $d2 = bless {}, 'DONE2'; bless sub {my $d1; my $d2; }, 'DONE3'; ( $outer = bless sub { $d1; $inner = bless sub { $d2; }, 'DONE4'; }, 'DONE5' )->(); } warn "free outer"; Scalar::Util::weaken $outer; warn "free inner"; Scalar::Util::weaken $inner; warn "free end"; __END__ [v5.8.8] free outer at - line 32. free inner at - line 34. d4:DONE4=CODE(0x82427c) at - line 11. d5:DONE5=CODE(0x800eac) at - line 14. d1:DONE1=HASH(0x800d80) at - line 2. free end at - line 36. d2:DONE2=HASH(0x800e34) at - line 5 during global destruction. [v5.10.0] free outer at - line 32. free inner at - line 34. d4:DONE4=CODE(0x1555338) at - line 11. d5:DONE5=CODE(0x14fc448) at - line 14. d2:DONE2=HASH(0x15554a0) at - line 5. d1:DONE1=HASH(0x14d7df0) at - line 2. free end at - line 36. -外の変数を使わないとクロージャとならない(DONE3は解放されない) -クロージャは内側から順に解放される($outerは$innerが消えるまで残る)。 -Perl 5.8系では、2つ外の参照を解放できない($d2はリーク)
AnyEvent使っててクロージャ絡みのリークがよくわからんかったので(とても原始的に)検証しただけのメモです。