为什么生命周期对 slice::from_raw_parts 很重要?

Why is the lifetime important for slice::from_raw_parts?

slice::from_raw_parts 的文档警告程序员用正确的生命周期注释切片。我假设,给定一些生命周期 'a,我可以使用

执行此注释
let myslice: &'a mut [i32] = std::slice::from_raw_parts_mut(ptr, sz)

我也假设

为什么我得到正确的生命周期很重要?设置切片生命周期时,释放后使用是唯一要担心的危险吗?

更新: 正如 delnan 所说,可变别名是一个真正的问题,可能由设置不正确的生命周期引起。有关详细信息,请参阅 his/her 答案。

旧答案

释放后使用确实是设置切片生命周期时唯一需要担心的危险。编译器将信任您并假定切片指向的数据与您指定的生命周期一样长。如果您的注释生命周期长于底层数据的实际生命周期,您最终可能会遇到释放后使用错误(您将能够在数据已被释放时使用切片)。

关于你的假设,它们是正确的。生命周期注释对数据的内存管理没有任何影响。

释放后使用不是唯一的危险。错误的生命周期会导致可变别名。让我们以这个(人为的)函数为例:

fn duplicate_mut_slice<'a, T>(xs: &mut [T]) -> &'a mut [T] {
    let ptr = xs.as_mut_ptr(); // btw, this part is safe!
    unsafe { std::slice::from_raw_parts_mut(ptr, xs.len()) }
}

由于生命周期的排列方式,这样的调用将会成功:

fn alias_first_element<T>(xs: &mut [T]) -> (&mut T, &mut T) {
    let a = duplicate_mut_slice(xs);
    let b = duplicate_mut_slice(xs);
    (&mut a[0], &mut b[0])
}

请注意,在第二个函数的签名中,生命周期是正确的,释放后使用不是(直接)危险。但是可变别名非常隐蔽。基本上一切都依赖于保证不存在可变别名,以防止竞争条件、迭代器失效、逻辑错误和释放后使用(由 管理的 T 等问题) ).可变别名几乎可以引起任何可以想象到的问题。