Skip to content

13.4 内存不安全示例:悬空指针

在具有指针的语言中,很容易通过释放内存时保留指向它的指针而错误地生成一个悬空指针(dangling pointer),所谓悬空指针是其指向的内存可能已经被分配给其它持有者。

相比之下,在 Rust 中编译器确保引用永远也不会变成悬空状态:当你拥有一些数据的引用,编译器确保数据不会在其引用之前离开作用域

让我们尝试创建一个悬空引用,Rust 会通过一个编译时错误来避免:

这段代码无法通过编译!

rust
fn main() {
    let reference_to_nothing = test_dangle();
}

fn test_dangle() -> &String { // dangle 返回一个字符串的引用

    let s = String::from("hello"); // s 是一个新字符串

    &s // 返回字符串 s 的引用
} // 这里 s 离开作用域并被丢弃。其内存被释放。
  // 危险!

因为s是在dangle函数内创建的,当dangle的代码执行完毕后,s将被释放。不过我们尝试返回它的引用。这意味着这个引用会指向一个无效的 String,Rust 不允许我们这么做!

这里的解决方法是直接返回 String:

rust
fn main() {
    let reference_to_nothing = test_dangle();
}

fn test_dangle() -> String {
    let s = String::from("hello");
    s
}

这样就没有任何错误了。所有权被移动出去,所以没有值被释放。

写 Rust 代码的时候,经常会有这样的感觉:Rust 编译器极其严格,甚至到了“不近人情”的地步。但是大部分时候却又发现,它指出来的问题的确是对我们编程有益的。对它使用越熟练,越觉得它是一个好帮手。

Released under the MIT License