Rust unsafe

unsafe 扩大信任边界而非关闭借用检查;能做什么、必须保证什么、如何封装安全抽象。

#type / concept #status / growing #tech / dev #resource / rust

[!info] 关联笔记

Rust unsafe

这个概念为什么出现

安全 Rust 无法表达所有底层操作(原始指针、某些 FFI、手工布局)。
unsafe 让你进入需要额外人工证明的区域,同时仍保留大量编译检查。

[!abstract] 一句话理解 unsafe 允许五类超能力(裸指针解引用、unsafe 函数、可变静态、union 字段、实现 unsafe trait);不变量由程序员保证,应用安全封装对外。

最小可运行示例

场景:安全封装——从裸指针读取需要信任的长度

演示“unsafe 块尽量小 + 安全函数边界检查”。

// 业务意图:在已校验长度的前提下读取首字节。
// 教学点:安全 API 做检查;unsafe 仅解引用。

fn first_byte(data: *const u8, len: usize) -> Option<u8> {
    if data.is_null() || len == 0 {
        return None;
    }
    // SAFETY: 调用方保证 data 指向至少 len 字节可读;我们已排除空与零长。
    // 此处示例假定调用方契约成立(教学用)。
    let b = unsafe { *data };
    Some(b)
}

fn main() {
    let buf = [9u8, 8, 7];
    println!("{:?}", first_byte(buf.as_ptr(), buf.len()));
    println!("{:?}", first_byte(std::ptr::null(), 0));
}

建议运行:cargo run

期望:

Some(9)
None

结合场景再看三个关注点

  1. SAFETY 注释写清前提
  2. 检查放在 safe 边界
  3. 最小化 unsafe 行数

核心概念与准确模型

unsafe 超能力(教学列表):

  1. 解引用裸指针
  2. 调用 unsafe fn
  3. 访问/修改可变静态
  4. 实现 unsafe trait
  5. 读 union 字段

未定义行为(UB)例子:悬垂、越界、数据竞争、无效枚举判别式…

安全抽象:对外 100% safe API,对内局部 unsafe。

设计动机

  • 系统编程需要底层
  • 把危险集中审查
  • 不逼所有代码进入 unsafe

边界与误区

  • “有 unsafe 就随便” → UB
  • 大范围 unsafe 块
  • 无测试/无 Miri

[!warning] 常见误区:用 unsafe 绕过借用检查偷懒 正确动机应是表达安全 Rust 无法表达且已证明的不变量。

工程实践

  1. 最小权限 unsafe
  2. 文档 + SAFETY 注释
  3. 用 Miri/测试加固
  4. 代码评审强制

本节总结

  • unsafe = 信任边界
  • 封装安全 API
  • 与 FFI/性能相关

自测题

  1. unsafe 会关闭借用检查吗?
  2. 为什么要写 SAFETY 注释?
参考答案
  1. 不会整体关闭;只允许额外操作。
  2. 记录证明义务,供审计与未来修改。

延伸阅读与资料来源

资料类型支撑内容
The Book — Unsafe Rust官方书unsafe
Rustonomicon官方不变量与 UB
Miri工具检测 UB
创建于 2026/7/15 更新于 2026/7/15