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 — это приведёт к "double panic" и аварийному завершению процесса.Вопрос: Что произойдет, если в процессе drop() структуры попытаться передать владение ресурсом в другую часть программы — например, вернуть его из drop?
Ответ: Нельзя "спасти" или передать значение поля структуры во время drop кому-либо другому, кроме самого дропа; попытка вернуть значение или передать его приведет к ошибке компиляции или нарушению безопасности памяти (если использовать unsafe). Пример ошибки:
impl Drop for MyStruct { fn drop(&mut self) -> T { // Error: Drop::drop cannot return a value! ... } }
История
В файловом процессоре забыли реализовать Drop для структуры, напрямую обёртывающей сырой файловый дескриптор. После сотен операций возникал "исчерпан лимит файловых дескрипторов" — ресурсы не очищались.
История
В сетевой библиотеке реализовали Drop для обёртки над TCP-соединением, но при drop происходил panic по ошибке закрытия сокета. Это приводило к аварийному завершению потока при double-panic (единственный способ — избегать panic в Drop!).
История
В системе плагинов попытались реализовать очистку с помощью Drop, создавая новые ресурсы во время drop (например, логирование в файл). Это привело к "already borrowed: BorrowMutError" из-за рекурсивного вызова drop для связанных структур и утечек ресурсов.