非安全操作
作为本节的介绍,引用自 官方文档,"应该尽量减少代码库中非安全代码的数量。" 考虑到这一点,让我们开始吧! Rust 中的 unsafe 注解用于绕过编译器设置的保护措施;具体来说,unsafe 主要用于以下四种情况:
- 解引用裸指针
- 调用被标记为
unsafe的函数或方法(包括通过 FFI 调用函数,参见本书的前一章) - 访问或修改静态可变变量
- 实现非安全 trait
裸指针
裸指针 * 和引用 &T 的作用类似,但引用总是安全的,因为借用检查器保证它们指向有效数据。对裸指针进行解引用只能在非安全块 (unsafe 块) 中进行。
fn main() { let raw_p: *const u32 = &10; unsafe { assert!(*raw_p == 10); } }
调用非安全函数
有些函数可以被声明为 unsafe,这意味着确保正确性的责任在于程序员而非编译器。一个例子是 std::slice::from_raw_parts,它根据指向第一个元素的指针和长度创建一个切片。
use std::slice; fn main() { let some_vector = vec![1, 2, 3, 4]; let pointer = some_vector.as_ptr(); let length = some_vector.len(); unsafe { let my_slice: &[u32] = slice::from_raw_parts(pointer, length); assert_eq!(some_vector.as_slice(), my_slice); } }
对于 slice::from_raw_parts,一个必须遵守的假设是传入的指针指向有效的内存,并且指向的内存类型是正确的。如果这些不变式没有得到遵守,那么程序的行为是未定义的,并且不知道会发生什么。