Perl5.10.0ではクロージャをネストしたときのメモリリークが解消されているみたい
Perl5.8まではクロージャをネストした場合にメモリーリークが発生するという問題がありましたが、5.10.0では解消されているようです。
例えば以下のようなソースを実行すると
use strict; use Devel::Leak::Object qw(GLOBAL_bless); package Foo; sub new { my $class = shift; return bless { id => shift }, $class; } sub DESTROY { my $self = shift; print "Destroy @{[$self->{id}]} $self\n"; } package main; sub main ($) { my $j = shift; print "# MAIN BLOCK START\n"; my $foo = Foo->new( $j ); sub { sub { print "id = $foo->{id}\n"; # 二つ以上外のローカル変数を参照 }->(); }->(); print "# MAIN BLOCK END\n"; } print "Perl Version is $]\n"; main($_) for (1..3)
5.6だと$fooは解放されずにすべてリークしてしまいます。
実行結果
Perl Version is 5.006001 # MAIN BLOCK START id = 1 # MAIN BLOCK END # MAIN BLOCK START id = 2 # MAIN BLOCK END # MAIN BLOCK START id = 3 # MAIN BLOCK END After main Tracked objects by class: Foo 3 Destroy 2 Foo=HASH(0x8143074) Destroy 3 Foo=HASH(0x8143158) Destroy 1 Foo=HASH(0x80f5714)
l5.8だと一回目の$fooのみ解放されずに残ってしまいます。
Perl Version is 5.008008 # MAIN BLOCK START id = 1 # MAIN BLOCK END # MAIN BLOCK START id = 2 # MAIN BLOCK END Destroy 2 Foo=HASH(0x81c399c) # MAIN BLOCK START id = 3 # MAIN BLOCK END Destroy 3 Foo=HASH(0x81c399c) After main Tracked objects by class: Foo 1 Destroy 1 Foo=HASH(0x8152b44)
これが5.10.0で実行するとちゃんと期待通り動作するようになっていました。
Perl Version is 5.010000 # MAIN BLOCK START id = 1 # MAIN BLOCK END Destroy 1 Foo=HASH(0x8167f20) # MAIN BLOCK START id = 2 # MAIN BLOCK END Destroy 2 Foo=HASH(0x8167f20) # MAIN BLOCK START id = 3 # MAIN BLOCK END Destroy 3 Foo=HASH(0x8167f20) After main Tracked objects by class:
Errorモジュールのtry catchなどで暗黙にクロージャが生成される場合等注意が必要でしたが5.10.0だと安心して使用できそうです。