无界生命周期
不安全代码通常最终会凭空产生引用或生命周期。这些生命周期以无界的形式出现。最常见的来源是对解引用的原始指针进行引用,这会产生一个具有无界生命周期的引用。这样的生命周期会根据上下文的需求变得尽可能大。实际上,这比简单地变为 '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Ӛ_` }
避免无界生命周期的最简单方法是在函数边界使用生命周期省略。如果省略了输出生命周期,那么它必须由输入生命周期绑定。当然,它可能被错误的生命周期绑定,但这通常只会导致编译器错误,而不是轻易地违反内存安全。
在函数内部,绑定生命周期更容易出错。绑定生命周期最安全和最简单的方法是从具有绑定生命周期的函数返回它。但是,如果这是不可接受的,则可以将引用放置在具有特定生命周期的位置。不幸的是,无法命名函数中涉及的所有生命周期。