Perl で tie を使った後 untie 時にどうしても「untie attempted while 1 inner references still exist」のワーニングが消えない事がある。意外なほど単純だったその理由。
結論
tied を使うとワーニングが出る
tie のワーニングに関する基本事項
Perl で、tie 時にその戻り値を変数で受けてしまうと、untie の前にその変数を undef してやらないとこのワーニングが出る。
ワーニングが出る例
use warnings;
use DB_File;
my %database;
my $x = tie(%database, “DB_File”, “hoge.dbm”, O_RDWR|O_CREAT, 0644, $DB_BTREE)
or die $!;
#何かの処理
untie %database;
このような場合は、untie する前に変数 $x を undef すればこの問題を回避できる。
ワーニングが出ない例
use warnings;
use DB_File;
my %database;
my $x = tie(%database, “DB_File”, “hoge.dbm”, O_RDWR|O_CREAT, 0644, $DB_BTREE)
or die $!;
#何かの処理
undef $x;
untie %database;
変数を使っていなくても untie でワーニングが出てしまう例
さて所で、そもそも tie する時に変数で受けなければただ untie してもワーニングは出ない。
ワーニングが出ない例 その2
use warnings;
use DB_File;
my %database;
tie(%database, “DB_File”, “hoge.dbm”, O_RDWR|O_CREAT, 0644, $DB_BTREE)
or die $!;
#何かの処理
untie %database;
ところが、このような書き方をしてもどうしてもワーニングが消えない事があった。
何故だ何故だとかなりハマったのだが、END サブルーチンでの終了処理として untie していたために以下のように書いていたのが原因だった。
untie でワーニングが出る書き方
untie %database if tied %database;
}
この「if tied %database」の一撃で内部的にリファレンスが生成されてしまうらしい。
もし untie 前に判別をするのであれば、以下のように一旦変数で受けた物を undef してやれば OK。
if ( $flg ) {
undef $flg;
untie %database;
}