Understanding (de)allocation

I am a bit confused about how string allocation and de-allocation works in rust.

Consider this piece of code:

use std::collections::HashMap;

pub fn main(){
    let mut map:HashMap<String,String> = HashMap::new();
    for _i in 1..1_000_000_000 {
        map.insert("bob".to_string(),
                   "fred".to_string());
    }
}

Now "bob" and "fred" are created on every iteration of the loop. When
"bob" gets inserted, the old "fred" gets removed.

So, why does this code not memory leak lots of "freds"?

Because "insert" returns ownership of the original "fred" to you and the original "bob" (that was the key) is dropped. Since you aren't doing anything with the "fred" returned by insert, is is dropped as well. In other words, the Rust compiler is "smart" and knows when what owns the "Fred" and "Bob" at any given time and knows when to free it (when ownership is ceded and it goes out-of-scope).

1 Like

The code that is actually run is:

pub fn main(){
    let mut map:HashMap<String,String> = HashMap::new();
    for _i in 1..1_000_000_000 {
        let tmp = map.insert("bob".to_string(),
                   "fred".to_string());
        drop(tmp);
    }
    drop(map);
}

Rust uses ownership rules and lifetimes to know where to insert drop() automatically, so that you never need to.

@gbutler69 Ah, yes, it was the return of the original entries that had me confused. I couldn't see how that was happening.

@kornel I know the theory, but understanding how it works is also important!