Test::LeakTraceのnot_leaked()

Test::LeakTrace 0.02でnot_leaked()がそこそこまともに動くようになった。与えられるブロックを一度実行した後にトレースするようにしたので,内部でキャッシュを使うシステムを考慮したうえで検証してくれる。

たとえばClass::Monadic 0.01を用いたコード:

#!perl -w
use strict;
use Test::More tests => 1;
use Test::LeakTrace 0.02;

use Class::Monadic; # v 0.01

not_leaked{
    my $o = bless{};
    Class::Monadic->initialize($o);
};

このコードを実行するといくつかのメモリリークがあると報告される。実際,ループ内でClass::Monadic->initialize()を実行するとメモリ消費量が増えてゆくことがわかる。つまり,Class::Monadicにはメモリリークがあることを検出できた。そしてそのログを解析し,実際にメモリリークを修正することができた*1

同じ方法でClass::MOP::Class->create_anon_class()を実行してみると,これまたメモリリークを起こしている。実際,ループ内で(以下略)

なお,Perlレベルからアクセスできないはずのデータ*2を返すことがあるので,Data::Dumperで出力しようとするとうまくいかないことがある。よって,ログの出力にはDevel::Peek::Dumpの実体であるsv_dump()を用いている。

*1:ただし,Perl 5.10.0にはウィークリファレンスでメモリリークが起きるという問題があるので,実際にはリークがゼロになることはない。

*2:たとえば,配列の要素に配列のリファレンスではなく配列そのものが入っている場合など。