Trait Drop は、リソースがスコープから出るときにカスタムのクリーンアップロジックを指定することを可能にします。通常、ファイル、ネットワーク、外部、及び安全でないリソースの解放に使用されます。Dropはコンパイラによって自動的に呼び出されます。
例:
struct FileWrapper { fd: i32, } impl Drop for FileWrapper { fn drop(&mut self) { println!("Closing fd: {}", self.fd); unsafe { libc::close(self.fd); } } } fn main() { let file = FileWrapper { fd: 42 }; } // dropは自動的に呼び出される
特徴:
file.drop()のように)。ただし、std::mem::drop(file)を介して呼び出すことはできます。panic!)を発生させるべきではありません。この場合、「ダブルパニック」が発生し、プロセスの異常終了につながる可能性があります。質問: drop()メソッドの途中でリソースの所有権をプログラムの別の部分に渡そうとするとどうなりますか?例えば、dropから戻すことはできますか?
回答: drop中に構造体のフィールドの値を他の誰か(ドロップ自身を除く)に渡したり「救ったり」することはできません。値を返したり渡したりしようとすると、コンパイルエラーやメモリ安全性の違反(unsafeを使用した場合)が発生します。エラーの例:
impl Drop for MyStruct { fn drop(&mut self) -> T { // エラー: Drop::dropは値を返せません! ... } }
事例
ファイルプロセッサで、生のファイルディスクリプタを直接ラップする構造体のDropを実装し忘れました。何百回も操作を行った後、「ファイルディスクリプタの制限が超過しました」というエラーが発生しました。リソースが解放されていませんでした。
事例
ネットワークライブラリでTCP接続のラッパーに対してDropを実装しましたが、drop中にソケットを閉じるエラーでpanicが発生しました。これはダブルパニックによるスレッドの異常終了を引き起こしました(唯一の対策はDrop内でpanicを避けることです!)。
事例
プラグインシステムで、Dropを使用してクリーンアップを実装し、drop中に新しいリソースを作成しようとしました(例えば、ファイルへのログ記録)。これにより、関連する構造体に対してdropが再帰的に呼び出され、「すでに借用されています: BorrowMutError」を引き起こし、リソースのリークが発生しました。