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