The Drop trait allows you to specify custom cleanup logic for a resource when it goes out of scope. It is commonly used for releasing file, network, external, and unsafe resources. Drop is called automatically by the compiler.
Example:
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 is called automatically
Features:
file.drop(), but you can call it through std::mem::drop(file).panic!) inside drop — this will lead to "double panic" and cause the process to terminate.Question: What happens if you try to transfer ownership of a resource to another part of the program during the drop() of a structure — for example, returning it from drop?
Answer: You cannot "save" or transfer a value of a structure field to anyone else during drop other than the drop itself; attempting to return a value or pass it will result in a compilation error or memory safety violation (if using unsafe). Example of an error:
impl Drop for MyStruct { fn drop(&mut self) -> T { // Error: Drop::drop cannot return a value! ... } }
Story
In a file processor, they forgot to implement Drop for a structure that directly wraps a raw file descriptor. After hundreds of operations, they encountered "file descriptor limit exceeded" — resources were not cleaned up.
Story
In a networking library, they implemented Drop for a wrapper over a TCP connection, but panic occurred during drop due to a socket closing error. This led to a thread termination due to a double panic (the only way — avoid panic in Drop!).
Story
In a plugin system, they attempted to implement cleanup using Drop by creating new resources during drop (e.g., logging to a file). This led to "already borrowed: BorrowMutError" due to recursive drop calls for related structures and resource leaks.