pointers-slices-safety
指针与切片安全边界(offset/add/wrapping 与 from_raw_parts 不变量)
指针算术与边界
ptr.add(n)/ptr.sub(n):以元素为单位偏移,不允许越过分配边界(allocation),溢出 UB。ptr.offset(n):允许负偏移,需更谨慎;新代码优先add/sub。wrapping_add/sub:在机器整数上环绕,但仍必须保持 provenance 和在同一 allocation 内的约束。- “one-past-end” 仅对原始指针在比较/再偏移时 合法;引用不允许指向越界位置。
from_raw_parts 的不变量
// SAFETY: 调用者必须保证:
// 1) ptr 源自同一分配(provenance)且对齐满足 T 的对齐要求
// 2) len 元素均已初始化(读取未初始化内存是 UB)
// 3) 内存不在切片存活期间被释放/收回
// 4) 对于 &mut [T],还需独占访问(无别名可变)
use std::slice;
use std::mem::MaybeUninit;
unsafe fn view_initialized(ptr: *const u32, len: usize) -> &'static [u32] {
slice::from_raw_parts(ptr, len)
}
// 对于部分初始化的缓冲区,先用 MaybeUninit 再安全转换:
unsafe fn assume_init_slice(buf: &[MaybeUninit<u32>]) -> &[u32] {
// 保证前 n 项已初始化
MaybeUninit::slice_assume_init_ref(buf)
}
拷贝语义与重叠
ptr::copy_nonoverlapping(memcpy):源与目标不应重叠;ptr::copy(memmove):允许重叠,但稍慢;- 用于
T,需确保按位复制符合T的有效性(对非Copy类型谨慎)。
对齐与未对齐访问
- 指针必须满足
align_of::<T>();不满足时使用read_unaligned/write_unaligned。 - packed 结构体字段访问需按字节处理或使用 unaligned 原语。
切片与长度
- 切片长度 按元素计;总字节 =
len * size_of::<T>()不能越过 allocation 大小。 - 空切片的指针可为任意非空对齐指针(不会被解引用)。
容器与失效引用
Vec的增长会 reallocate,String同理;持有元素引用时避免触发增长操作。- 使用索引或下标位置重新获取引用;或使用
Vec::reserve预留容量避免重分配。