Skip to content

13.2 内存不安全示例:修改枚举

Rust 设计的这个原则,究竟有没有必要呢?它又是如何在实际代码中起到“内存安全”检查作用的呢?

第一个示例,我们用 enum 来说明。假如我们有一个枚举类型:


rust
enum StringOrInt {
    Str(String),
    Int(i64),
}

它有两个元素,分别可以携带 String 类型的信息以及 i64 类型的信息。假如我们有一个引用指向了它的内部数据,同时再修改这个变量,大家猜想会发生什么情况?这样做可能会出现内存安全问题,因为我们有机会用一个 String 类型的指针指向 i64 类型的数据,或者用一个 i64 类型的指针指向 String 类型的数据。完整示例如下:

rust
use std::fmt::Debug;

#[derive(Debug)]
enum StringOrInt {
    Str(String),
    Int(i64),
}

fn main() {
    use StringOrInt::{Str, Int};
    let x = Str("Hello world".to_string());

    if let Str(ref insides) = x {
        x = Int(1);
        println!("inside is {}, x says: {:?}", insides, x);
    }
}

在这段代码中,我们用if let语法创建了一个指向内部 String 的指针,然后在此指针的生命周期内,再把x内部数据变成 i64 类型。这是典型的内存不安全的场景。

幸运的是,这段代码编译不通过,错误信息为:

error[E0506]: cannot assign to `x` because it is borrowed

这个例子给了我们一个直观的感受,为什么 Rust 需要“可变性和共享性不能同时存在”的规则?保证当前只有一个访问入口,这是保证安全的可靠做法。

Released under the MIT License