解引用裸指针的步骤?

解读

在国内 Rust 岗位面试中,“裸指针”const T / mut T)属于 unsafe 块** 必考点。面试官想确认两点:

  1. 你是否清楚裸指针与引用的本质区别(无生命周期、无借用检查、可空、可悬垂);
  2. 你是否掌握**“三步走”安全仪式**:校验非空 → 对齐检查 → 用 unsafe 块解引用,并能在答题时主动提及 std::ptr::read/write/offset 等标准函数。
    答得太简略(只写 *ptr)会被追问“万一空指针怎么办”;答得太深(直接聊 MMU 页表)又容易“过度设计”。因此,给出**“编译期 + 运行期”双保险步骤**最合国内面试官口味。

知识点

  1. 裸指针类型:*const T / *mut T,不实现 Send/Sync,默认不保证对齐与初始化。
  2. 解引用唯一入口:必须放在 unsafe {} 块内,编译器放弃检查,程序员自负其责。
  3. 空指针校验:使用 is_null() 方法,与 C 的 ptr == NULL 对应。
  4. 对齐检查:利用 ptr as usize % mem::align_of::<T>() == 0,防止未对齐 UB。
  5. 标准库辅助:
    • std::ptr::read(ptr) / write(ptr, val) —— 避免移动语义异常;
    • offset / wrapping_offset / add —— 指针算术,需保证 in-bounds;
    • NonNull<T> —— 封装非空保证,可与 Box::into_raw 配对使用。
  6. 内存模型:Rust 采用 LLVM dereferenceable 属性,若指针无效即触发 UB,国内大厂代码审计会直接打回。
  7. 常见坑:
    • 解引用后临时引用不得越过 unsafe 块边界,否则产生 unbound lifetime
    • 多线程场景需自行加 AtomicPtrMutex,裸指针本身不提供同步。

答案

步骤如下,缺一不可

  1. 空指针校验if ptr.is_null() { return Err("null"); }
  2. 对齐校验assert!((ptr as usize) % mem::align_of::<T>() == 0);
  3. unsafe 块内解引用
    unsafe {
        // 若只读
        let val = *ptr;
        // 若写
        *ptr = new_val;
        // 或利用 std::ptr::read/write 避免 Drop 冲突
    }
    
  4. (可选但加分)生命周期收敛:把得到的引用 &*ptr&mut *ptrstd::mem::replaceManuallyDrop 包裹,防止越过 unsafe 块泄漏生命周期。

一句话总结:“先判空,再对齐,最后 unsafe 解引用;任何一步省掉,UB 等着你。”

拓展思考

  1. 与 C/C++ 交互
    通过 extern "C" FFI 拿到 *const c_char 后,先用 CStr::from_ptr非空 + 0 结尾双重校验,再转 &str,可展示你对跨语言内存安全的成熟认知。
  2. 零拷贝网络框架
    国内云原生面试常问 tokio + mmap,把裸指针映射到 &[u8] 切片时,需用 slice::from_raw_parts 并保证 *length mem::size_of::<T>() 不越页,否则内核发 SIGBUS
  3. ** Miri 与 KASAN**:
    回答完“三步走”后,可主动补充“CI 阶段跑 Miri 检测 UB”,或“Linux 内核模块用 KASAN + Rust 裸指针”,让面试官感受到你对国内大厂质量门禁的贴合。