Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is the storage reclaimed for a resource that is no longer owned?

There is a vector resource that is allocated in line 2 of the program below. When the program ends, the vector resource is not owned. If a resource is not owned at all, when does it get reclaimed? Is there an explanation using the terminology of Rust ownership semantics and lifetimes that could convince a programmer that this resource is indeed reclaimed?

fn main() {
    let mut v = vec![1,2];
    v = vec![3, 4];
}
like image 288
Anthony Maida Avatar asked Aug 12 '15 02:08

Anthony Maida


1 Answers

when does [an unowned resource] get reclaimed?

In Rust terms, an item is dropped when it goes out of scope, which often (but not always) corresponds to the end of a block. When it is dropped, any resources that are part of the item are also released.

Resources can mean memory, as in the vector example, but it can also correspond to other things like a file handle or a lock. This is commonly referred to as Resource Acquisition Is Initialization (RAII).

convince a programmer that this resource is indeed reclaimed?

You can never convince someone who truly doesn't want to believe ^_^. However, you can implement Drop yourself to see when an item is being dropped:

struct NoisyDrop(u8);

impl Drop for NoisyDrop {
    fn drop(&mut self) {
        println!("Number {} being dropped", self.0);
    }
}

fn main() {
    println!("step 1");
    let mut nd = NoisyDrop(1);
    println!("step 2");
    nd = NoisyDrop(2);
    println!("step 3");
}

This will have the output

step 1
step 2
Number 1 being dropped
step 3
Number 2 being dropped

You can see that the first variable is dropped when its binding is replaced as there's no longer any way to get to the NoisyDrop(1) value. The second variable is dropped when it goes out of scope due to the method ending.

ownership semantics and lifetimes

Consider this example:

fn main() {
    let mut v = vec![1];
    v = vec![2];
}

Conceptually, it could be written as

fn main() {
    {
        let v = vec![1];
    }
    {
        v = vec![2];
    }
}

And this example

fn main() {
    let v1 = vec![1];
    let v2 = vec![2];
}

Could be rewritten as

fn main() {
    {
        let v1 = vec![1];
        {
            let v2 = vec![2];
        }
    }
}

These rewritings show the lifetime of each variable. Whenever you call a method with a generic lifetime parameter, the lifetime of the block will be the concrete value that gets substituted for the 'a generic.

like image 52
Shepmaster Avatar answered Nov 13 '22 20:11

Shepmaster