Function core::slice::from_raw_parts

1.0.0 (const: 1.64.0) · source ·
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
Expand description

根据指针和长度形成切片。

len 参数是 元素 的数量,而不是字节数。

Safety

如果违反以下任一条件,则行为是未定义的:

  • 对于 len * mem::size_of::<T>() 多个字节的读取,data 必须是 valid,并且必须正确对齐。这尤其意味着:

    • 该切片的整个存储范围必须包含在一个分配的对象中! 切片永远不能跨越多个分配的对象。请参见 下文 了解一个没有考虑到这一点的错误示例。
    • 即使对于零长度切片,data 也必须非空且对齐。 这样做的一个原因是,枚举布局优化可能依赖于对齐的引用 (包括任何长度的切片) 和非空值,以将它们与其他数据区分开。 您可以使用 NonNull::dangling() 获得可用作零长度切片的 data 的指针。
  • data 必须指向 len 类型的 T 类型的连续正确初始化值。

  • 返回的切片引用的内存在生命周期 'a 期间不得更改,除非在 UnsafeCell 内部。

  • 切片的总大小 len * mem::size_of::<T>() 必须不大于 isize::MAX。 请参见 pointer::offset 的安全文档。

Caveat

从使用中可以推断出返回切片的生命周期。 为防止意外滥用,建议将生命周期与生命周期中任何安全的来源联系起来,例如通过提供一个辅助函数,获取切片的宿主值的生命周期,或通过明确的注解法。

Examples

use std::slice;

// 显示单个元素的切片
let x = 42;
let ptr = &x as *const _;
let slice = unsafe { slice::from_raw_parts(ptr, 1) };
assert_eq!(slice[0], 42);
Run

用法不正确

下面的 join_slices 函数是不健全的 ⚠️

use std::slice;

fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] {
    let fst_end = fst.as_ptr().wrapping_add(fst.len());
    let snd_start = snd.as_ptr();
    assert_eq!(fst_end, snd_start, "Slices must be contiguous!");
    unsafe {
        // 上面的断言确保 `fst` 和 `snd` 是连续的,但是它们仍可能包含在 _different allocated objects_ 中,在这种情况下,创建此切片是未定义的行为。
        slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len())
    }
}

fn main() {
    // `a` 和 `b` 是不同的分配对象...
    let a = 42;
    let b = 27;
    // ... 尽管如此,它仍然可以在内存中连续布局: | 一个 | b |
    let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB
}
Run