无界生命周期
非安全代码常常会凭空产生引用或生命周期。这类生命周期以无界的形式出现。最常见的来源是对解引用的裸指针取引用,这会产生一个具有无界生命周期的引用。这样的生命周期会根据上下文需要变得尽可能大。事实上,这比简单地变成 'static 更强大,因为例如 &'static &'a T 将无法通过类型检查,但无界生命周期会根据需要完美地适配成 &'a &'a T。然而,在大多数情况下,这样的无界生命周期可以被视为 'static。
几乎没有引用是 'static 的,所以这很可能是不对的。transmute 和 transmute_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Ӛ_` }
避免无界生命周期的最简单方法是在函数边界使用生命周期省略。如果输出生命周期被省略,那么它必须由一个输入生命周期来约束。当然,它可能被一个错误的生命周期所约束,但这通常只会导致编译器错误,而不是轻易地破坏内存安全。
在函数内部,约束生命周期更容易出错。最安全、最简单的方法是将其从一个具有绑定生命周期的函数中返回。然而,如果这不可接受,可以将引用放置在一个具有特定生命周期的地方。遗憾的是,不可能命名函数中涉及的所有生命周期。