无界生命周期

不安全的代码通常最终会凭空产生引用或生命周期。这样的生命周期以*无界*的形式进入世界。最常见的来源是对解引用后的原始指针进行引用,这会产生一个具有无界生命周期的引用。这样的生命周期会根据上下文的需求变得尽可能大。这实际上比简单地变成 'static 更强大,例如 &'static &'a T 将无法通过类型检查,但无界生命周期将根据需要完美地塑造成 &'a &'a T。然而,在大多数情况下,这样的无界生命周期可以被视为 'static

几乎没有引用是 'static 的,所以这可能是错误的。transmutetransmute_copy 是另外两个主要的罪魁祸首。应该尽量快速地绑定无界生命周期,尤其是在函数边界之间。

给定一个函数,任何不从输入派生的输出生命周期都是无界的。例如

fn get_str<'a>(s: *const String) -> &'a str {
    unsafe { &*s }
}

fn main() {
    let soon_dropped = String::from("hello");
    let dangling = get_str(&soon_dropped);
    drop(soon_dropped);
    println!("Invalid str: {}", dangling); // Invalid str: gӚ_`
}

避免无界生命周期的最简单方法是在函数边界使用生命周期省略。如果省略了输出生命周期,那么它*必须*由输入生命周期绑定。当然,它可能被*错误*的生命周期绑定,但这通常只会导致编译器错误,而不是让内存安全被轻易地破坏。

在函数内部,绑定生命周期更容易出错。绑定生命周期的最安全、最简单的方法是从具有绑定生命周期的函数返回它。然而,如果这是不可接受的,则可以将引用放置在具有特定生命周期的位置。不幸的是,不可能命名函数中涉及的所有生命周期。