tiedは、Perlの強力なメカニズムで、標準的な変数の動作をカスタムロジック(特別なインターフェースを実装したオブジェクトを通じて)で置き換えることができます。通常、変数をサードパーティのストレージや非標準の動作(例えば、キャッシュ、データベース、オンリー暗号化)に結びつけるために使用されます。
package FileHash; use Storable; sub TIEHASH { my ($class, $file) = @_; my $data = -e $file ? retrieve($file) : {}; bless { file => $file, data => $data }, $class; } sub STORE { my ($s, $k, $v) = @_; $s->{data}{$k} = $v; store($s->{data}, $s->{file}); } sub FETCH { my ($s, $k) = @_; $s->{data}{$k} } sub EXISTS { my ($s, $k) = @_; exists $s->{data}{$k} } sub DELETE { my ($s, $k) = @_; delete $s->{data}{$k}; store($s->{data}, $s->{file}); } sub CLEAR { my $s = shift; $s->{data} = {}; store($s->{data}, $s->{file}); } 1; # 使用: tie my %hash, 'FileHash', '/tmp/data.store'; $hash{x} = 42; print $hash{x};
TIEHASH、FETCH、STORE、EXISTS、DELETE、CLEARメソッドを実装する必要があります。TIESCALAR)、配列(TIEARRAY)、およびハッシュ(TIEHASH)のために機能します。質問: untie関数を使用して変数を通常の動作に戻すことはできますか、その場合何が起こりますか?
回答: untie %hash;を使用した後、変数に対する今後の操作はオブジェクトとの接続を失いますが、内部のデストラクタメソッド(DESTROY)は変数が完全に破棄された後にのみ呼び出されます。untieを呼び出さなかった場合、スクリプトの終了時にデータが保存されなかったり、メモリリークが発生する可能性があります。
tie my %h, 'SomeClass'; # ... 作業を続ける ... untie %h; # これによりオブジェクトの処理が正しく終了します
ストーリー 情報システムでは、ハッシュのキャッシュを
tieを使用して実装しましたが、クリーニングメソッドを正しく呼び出すことを忘れました(untie)。その結果、サービスの再起動時にキャッシュが増え続け、メモリが解放されませんでした。
ストーリー 監査ログでは
TIEARRAYを使用してイベントを保存しましたが、その中でメソッドの一部だけを継承しました。その結果、要素を削除しようとすると、未初期化メソッドによるキャッチしにくいエラーが発生しました。
ストーリー
tieを使って内容の透過的な暗号化を実装する際、数多くのCPANモジュールが直接Perlの内部メソッドを使用し、tieインターフェースをバイパスしていることを考慮に入れるのを忘れました。そのため、データが時折未暗号化の状態で保存されました。