通过一个例子简单理解rust的生命周期与内存安全性

建议配合the book一起食用

fn main() {
    let mut result_ref = &mut 0;
    *result_ref = 1;
    {
        let num1 = 1;
        let mut num2 = 2;
        let arg1 = &num1;
        {
            let arg2 = &mut num2;
            result_ref = lifetime(arg1, arg2);
        }
        println!("Hello, {}!", result_ref);
    }
    *result_ref = 233; // UAF occurs here
}

fn lifetime<'a>(_x: &i32, y: &'a mut i32) -> &'a mut i32 {
    y
}

无法编译,因为当试图赋值233的时候,访问result_ref指向的地址(前面作用域结束时已经被释放的num2)是非法的。

error[E0597]: `num2` does not live long enough
  --> src\main.rs:9:24
   |
9  |             let arg2 = &mut num2;
   |                        ^^^^^^^^^ borrowed value does not live long enough
...
13 |     }
   |     - `num2` dropped here while still borrowed
14 |     *result_ref = 233;
   |     ----------------- borrow later used here

lifetime的签名保证了result_ref(地址)只在num2有效的作用域里有效。但是,但是,但是,仅此而已,虽然result_ref的值是一个非法的地址,但result_ref本身还在作用域内是可以被访问的。


稍作修改:
result_ref = &mut 233;
这次试图把一个存储字面量233的新地址赋给result_ref,但不再使用它,成功编译,输出:
Hello, 2!

因为这个字面量只是临时的,赋值语句结束之后就被释放掉了,之后再尝试使用result_ref会遇到和前面一样的问题:

14 |     result_ref = &mut 233;
   |                       ^^^- temporary value is freed at the end of this statement
   |                       |
   |                       creates a temporary which is freed while still in use
15 |     println!("Hello, {}!", result_ref);
   |                            ---------- borrow later used here

点击右边的按钮加载评论,如果无法加载那估计是被墙啦..你看着办w