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() 明确调用值的drop,但可以通过 std::mem::drop(file) 来调用。panic!) — 这会导致 "double panic" 和进程崩溃。问题: 如果在结构体的drop()过程中尝试将资源的所有权传递给程序的其他部分 — 例如,从drop返回资源,会发生什么?
答案: 在drop期间,不能 "拯救" 或将结构字段的值传递给其他任何人;尝试返回值或传递它将导致编译错误或内存安全问题(如果使用un安全)。错误示例:
impl Drop for MyStruct { fn drop(&mut self) -> T { // 错误:Drop::drop不能返回一个值! ... } }
故事
在文件处理器中,忘记为直接包装原始文件描述符的结构实现Drop。经过数百次操作后出现 "文件描述符限制已达" — 资源没有被清理。
故事
在网络库中,为TCP连接的包装实现了Drop,但在drop时由于关闭soket时出现错误导致panic。这导致在双重panic时线程崩溃(唯一的方法是避免在Drop中发生panic!)。
故事
在插件系统中,试图通过Drop进行清理,在drop期间创建新资源(例如日志记录到文件)。这导致 "already borrowed: BorrowMutError" 由于对相关结构的递归调用drop和资源泄漏。