解引用裸指针
创建指针是安全的操作,但解引用指针需要使用 unsafe
方法:
fn main() { let mut x = 10; let p1: *mut i32 = &raw mut x; let p2 = p1 as *const i32; // SAFETY: p1 and p2 were created by taking raw pointers to a local, so they // are guaranteed to be non-null, aligned, and point into a single (stack-) // allocated object. // // The object underlying the raw pointers lives for the entire function, so // it is not deallocated while the raw pointers still exist. It is not // accessed through references while the raw pointers exist, nor is it // accessed from other threads concurrently. unsafe { dbg!(*p1); *p1 = 6; // Mutation may soundly be observed through a raw pointer, like in C. dbg!(*p2); } // UNSOUND. DO NOT DO THIS. /* let r: &i32 = unsafe { &*p1 }; dbg!(r); x = 50; dbg!(r); // Object underlying the reference has been mutated. This is UB. */ }
This slide should take about 10 minutes.
我们建议(而且 Android Rust 样式指南要求)为每个 unsafe
代码块编写一条注释, 说明该代码块中的代码如何满足其所执行的不安全操作的 安全要求。
对于指针解除引用,这意味着指针必须为 valid,即:
- 指针必须为非 null。
- 指针必须是 dereferenceable(在单个已分配对象的边界内)。
- 对象不得已取消分配。
- 不得并发访问相同位置。
- 如果通过转换引用类型来获取指针,则底层对象必须处于活跃状态, 而且不得使用任何引用来访问内存。
在大多数情况下,指针还必须正确对齐。
The “UNSOUND” section gives an example of a common kind of UB bug: naïvely taking a reference to the dereference of a raw pointer sidesteps the compiler’s knowledge of what object the reference is actually pointing to. As such, the borrow checker does not freeze x
and so we are able to modify it despite the existence of a reference to it. Creating a reference from a pointer requires great care.