Skip to content

Rust Unsafe Rust

Rust 提供了 unsafe 关键字来编写不安全的代码。本章节将介绍 Rust 中的 unsafe 代码。

什么是 Unsafe Rust

Unsafe Rust 是 Rust 中的一个特性,它允许我们:

  • 解引用原始指针
  • 调用 unsafe 函数
  • 访问或修改可变静态变量
  • 实现 unsafe trait
  • 访问 union 的字段

Unsafe 代码块

使用 unsafe 关键字创建 unsafe 代码块:

rust
fn main() {
    let mut num = 5;
    
    // 创建原始指针
    let raw_ptr = &mut num as *mut i32;
    
    // 在 unsafe 代码块中解引用原始指针
    unsafe {
        *raw_ptr = 10;
        println!("Value: {}", *raw_ptr);
    }
    
    println!("num: {}", num);
}

原始指针

Rust 有两种原始指针类型:

  • *const T:不可变原始指针
  • *mut T:可变原始指针
rust
fn main() {
    let mut num = 5;
    
    // 创建不可变原始指针
    let const_ptr: *const i32 = &num as *const i32;
    
    // 创建可变原始指针
    let mut_ptr: *mut i32 = &mut num as *mut i32;
    
    unsafe {
        println!("const_ptr: {}", *const_ptr);
        *mut_ptr = 10;
        println!("mut_ptr: {}", *mut_ptr);
    }
}

Unsafe 函数

使用 unsafe 关键字定义 unsafe 函数:

rust
unsafe fn dangerous() {
    // 执行不安全操作
    println!("This is a dangerous function");
}

fn main() {
    // 调用 unsafe 函数需要在 unsafe 代码块中
    unsafe {
        dangerous();
    }
}

静态变量

静态变量在程序的整个生命周期内都存在:

rust
// 不可变静态变量
static HELLO: &str = "Hello, world!";

// 可变静态变量
static mut COUNTER: u32 = 0;

fn main() {
    println!("{}", HELLO);
    
    // 访问可变静态变量需要在 unsafe 代码块中
    unsafe {
        COUNTER += 1;
        println!("COUNTER: {}", COUNTER);
    }
}

Unsafe Trait

使用 unsafe 关键字定义 unsafe trait:

rust
unsafe trait UnsafeTrait {
    fn do_something(&self);
}

struct MyType;

// 实现 unsafe trait 需要使用 unsafe 关键字
unsafe impl UnsafeTrait for MyType {
    fn do_something(&self) {
        println!("Doing something unsafe");
    }
}

fn main() {
    let my_type = MyType;
    my_type.do_something();
}

Union

Union 是一种可以存储不同类型值的类型:

rust
union MyUnion {
    i: i32,
    f: f32,
}

fn main() {
    let mut u = MyUnion { i: 42 };
    
    // 访问 union 的字段需要在 unsafe 代码块中
    unsafe {
        println!("u.i: {}", u.i);
        u.f = 3.14;
        println!("u.f: {}", u.f);
    }
}

Unsafe 代码的最佳实践

  1. 尽量避免使用 unsafe 代码:只在必要时使用 unsafe 代码。

  2. 最小化 unsafe 代码的范围:将 unsafe 代码限制在尽可能小的范围内。

  3. 添加安全抽象:在 unsafe 代码之上提供安全的 API。

  4. 文档化 unsafe 代码:清楚地记录 unsafe 代码的使用原因和安全性保证。

  5. 测试 unsafe 代码:确保 unsafe 代码的正确性。

示例:安全的抽象

rust
// 不安全的底层实现
unsafe fn unsafe_add(a: *const i32, b: *const i32) -> i32 {
    *a + *b
}

// 安全的抽象
fn safe_add(a: &i32, b: &i32) -> i32 {
    unsafe {
        unsafe_add(a, b)
    }
}

fn main() {
    let x = 5;
    let y = 10;
    println!("{} + {} = {}", x, y, safe_add(&x, &y));
}

总结

  • Unsafe Rust:允许执行不安全操作的 Rust 代码
  • Unsafe 代码块:使用 unsafe 关键字创建
  • 原始指针*const T*mut T
  • Unsafe 函数:使用 unsafe 关键字定义
  • 静态变量:特别是可变静态变量
  • Unsafe Trait:需要使用 unsafe 关键字实现
  • Union:需要在 unsafe 代码块中访问字段
  • 最佳实践:尽量避免使用,最小化范围,添加安全抽象,文档化,测试

Unsafe Rust 是 Rust 中的一个强大特性,它允许我们执行一些 Rust 安全系统不允许的操作。通过本章节的学习,你应该已经了解了 Rust 中 unsafe 代码的基本概念和使用方法。