建议配合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