直接回答:unsafe 只解锁五种能力:解引用裸指针、调用 unsafe 函数(含 FFI)、读写可变静态变量、实现 unsafe trait(Send/Sync 等)、访问 union 字段。它不关闭借用检查器,不豁免生命周期和类型检查,只是把"这段代码的内存安全由我人工担保"告诉编译器。正确姿势是把 unsafe 限制在最小作用域,外面包一层安全 API,把人工担保封装成类型层面的保证。
展开解析:工程纪律:unsafe 块上方写注释说明满足了哪些前置条件(invariants),为什么安全;能拆成两个 safe 操作加一个小 unsafe 的,不要整函数标 unsafe。典型合法场景:FFI 绑定(校验指针非空、长度可信后再转 slice)、手工优化(get_unchecked 跳过已证明的边界检查)、实现内核数据结构。典型翻车:把裸指针存起来长期持有(所有权漂移后悬垂)、transmute 改类型绕过检查、跨 FFI 传递 Rust 所有权导致双重释放。工具上,Miri 解释器能检测未定义行为,cargo geiger 审计 unsafe 用量。记住衡量标准:safe 代码无论怎么调用你的安全封装都不应产生 UB——违反这条就是封装有洞。
追问方向:什么是 stacked borrows / tree borrows 模型?为什么 mem::transmute 几乎总是错的?unsafe trait 与 unsafe fn 的区别?
(约 470 字)