原始指针的unsafe方法.offset()具有以下安全要求:

如果违反了以下任何条件,则结果为Undefined Behavior:

  • 起始指针和结果指针都必须是either in bounds or one byte past,即同一分配对象的结尾.
  • ...

我感到困惑的是,如果结果的原始指针指向所述边界之外,事情怎么可能出错.我的印象是,如果一个原始指针从未被取消引用,它总是安全的,无论如何,因为我可以创建一个原始指针在稀薄的空气中完全安全的语句:

let val = 42usize;
let ptr = val as *mut i32;

有没有任何例子表明创建一个通过.offset()的野生指针会导致程序崩溃,而通过强制转换则不会?

推荐答案

在文档的结尾处解释了为什么offset的安全要求非常保守:

如果这些约束难以满足,则考虑使用wrapping_offset.这种方法的唯一优点是it enables more aggressive compiler optimizations.

我的重点

另一种方法wrapping_offset允许我们任意偏移指针.不同的是

该方法基本上是停留在同一分配对象内的delays the requirement.[...] wrapping_offset产生一个指针,但如果指针在它所附着的对象的边界外时被取消引用,则仍然会导致未定义的行为.

另一方面,

offsetimmediate Undefined Behavior,当跨越物体边界时.

offset的安全要求更保守,

offset可以被更好地优化,因此在性能敏感的代码中是首选的.

所以,原则上,在分配之外产生指针的指针算术是安全的,只是不能使用offset来计算它们.

Rust相关问答推荐

在rust中如何修改一个盒装函数并将其赋回?

把Vector3变成Vector4的绝妙方法

通过解引用将值移出Box(以及它被脱糖到什么地方)?

无符号整数的Rust带符号差

应为关联类型,找到类型参数

为什么HashMap::get和HashMap::entry使用不同类型的密钥?

在 Rust 中用问号传播错误时对类型转换的困惑?

在什么情况下 `..._or()` 比 `..._or_else(|| {})` 更好,为什么?

如何重命名 clap_derive 中的子命令占位符?

如何为整数切片定义一个带有额外函数的特性别名?

实现泛型的 Trait 方法中的文字

如何递归传递闭包作为参数?

如何将这些测试放在一个单独的文件中?

在线程中运行时,TCPListener(服务器)在 ip 列表中的服务器实例之前没有从客户端接受所有客户端的请求

不能将 `*self` borrow 为不可变的,因为它也被borrow 为可变的 - 编译器真的需要如此严格吗?

产生拥有值的迭代器的 Rust 可变borrow 在循环中失败

将一片字节复制到一个大小不匹配的数组中

当我在 struct 中存储异步函数时,为什么它需要生命周期

隐式类型闭包的错误生命周期推断

加入动态数量的期货