Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

不安全操作

作为本节的引言,借用官方文档的话说:“应该尽量减少代码库中不安全代码的数量。“牢记这一点,让我们开始吧!Rust 中的不安全标注用于绕过编译器设置的保护机制。具体来说,不安全主要用于以下四个方面:

  • 解引用裸指针
  • 调用被标记为 unsafe 的函数或方法(包括通过 FFI 调用函数,参见本书前面的章节)
  • 访问或修改静态可变变量
  • 实现不安全特征
  • accessing elements of a union

裸指针

裸指针 * 和引用 &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,必须遵守的一个假设是:传入的指针指向有效内存,且指向的内存类型正确。如果这些不变量未被遵守,那么程序的行为将是未定义的,无法预知会发生什么。

Union Elements

Elements of unions overlap in memory, thus changing the value of one element automatically changes every element’s value. They can be used, if you don’t know which data type you will need at runtime. Since Rust offers safe Enums, the main purpose of Unions is to allow interacting with C code. Accessing and changing elements of unions is only allowed in unsafe Rust.

union MyFirstUnion {
    float: f32,
    integer: u32
}

fn main() {
    // Creating an object of a union type doesn't require Unsafe Rust.
    let mut u = MyFirstUnion { float: 123.45 };
    
    // Reading and changing u.float or u.integer is only allowed in Unsafe Rust.
    unsafe {
        assert_eq!(u.float, 123.45);
        println!("u.float = 123.45, but u.integer = {}", u.integer);

        u.integer = 42;
        assert_eq!(u.integer, 42);
        println!("u.integer = 42, but u.float = {}", u.float);
    }
}