Search code examples
pointersrustsmart-pointers

Actual use cases for the Drop trait in Rust?


I've been reading the Rust book, and in chapter 15.3 they introduce the Drop trait. It says the trait is important for implementing smart pointers ("The second trait important to the smart pointer pattern is Drop"), but from the example provided I fail to see why:

struct CustomSmartPointer {
    data: String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("Dropping CustomSmartPointer with data `{}`!", self.data);
    }
}

fn main() {
    let c = CustomSmartPointer {
        data: String::from("my stuff"),
    };
    let d = CustomSmartPointer {
        data: String::from("other stuff"),
    };
    println!("CustomSmartPointers created.");
}

They simply print the value owned by the container before it goes out of scope (from what I understand, it would've been dropped regardless).

About that, they say: "We’re printing some text here to demonstrate visually when Rust will call drop."

Right, but then no example is provided to show how the trait could actually be useful (except for maybe logging resources being released, I guess).

So my question is: how was the Drop implementation important in this case? Does ommiting it somehow cause a memory leak or something? I feel like I'm missing the point entirely. Can someone provide an use case that does anything besides just printing values before they're out of scope?

I tried removing the drop implementation, but that didn't change anything, except for the fact that nothing was printed when the CustomSmartPointer went out of scope. No compiler errors.


Solution

  • There's plenty of cases when you might want to perform some action when a value is dropped.

    • You're manually managing memory. This doesn't even have to be using native APIs; it could be using Box::into_raw/Box::leak and Box::from_raw.
    • You're implementing a Rust interface on top of a native OS resource, like file handles or network sockets. When the Rust-side value is dropped, you need to tell the OS to destroy the resource.
    • You're implementing a Rust interface on top of some third-party library. Consider something like SQLite, libpcap, etc. You want to clean up the resource in that library when the Rust handle is dropped.
    • You're implementing a guard, like RefCell or Mutex guards. When the guard is dropped, you need to adjust a reference count or release a lock.
    • You're implementing a connection pool. When a pooled connection is dropped, you want to return the connection to the pool so that it can be reused later.
    • And so on...

    It's probably rare that you'll need to manually implement Drop in most applications. However, it is a crucial part of the RAII idiom and so you'll see it used in places implementing that idiom.