← [ BACK_TO_NOTES ]

Rust Drop 与 RAII

离开作用域时 Drop 释放资源;RAII 把获取与释放绑定到生命周期;与 defer 思维对照。

#concept #growing #dev #rust

[!info] related notes

Rust Drop 与 RAII

这个概念为什么出现

文件句柄、锁、内存、socket 都需要成对获取/释放。
Rust 用所有权 + Drop trait 实现 RAII:所有者结束生命时自动清理,减少“忘记 close”。

[!abstract] 一句话理解 实现 Drop 的类型在离开作用域(或显式 drop)时运行析构逻辑;RAII 意味着资源寿命等于拥有者的寿命。

最小可运行示例

场景:模拟会话守卫——观察作用域退出日志

SessionGuard 仅模拟资源守卫,正常返回或提前 Err 时打印 release;它没有实现令牌撤销、持久化审计或真实鉴权。

// 业务意图:模拟获取/释放会话资源。
// 教学点:自定义 Drop;作用域结束自动调用;提前 return 也触发。

struct SessionGuard {
    user_id: u64,
}

impl SessionGuard {
    fn acquire(user_id: u64) -> Self {
        println!("acquire user={user_id}");
        Self { user_id }
    }
}

impl Drop for SessionGuard {
    fn drop(&mut self) {
        println!("release user={}", self.user_id);
    }
}

fn handle(user_id: u64, fail: bool) -> Result<(), String> {
    let _guard = SessionGuard::acquire(user_id);
    if fail {
        return Err("biz error".into()); // drop 仍会发生
    }
    println!("handle ok");
    Ok(())
}

fn main() {
    let _ = handle(7, true);
    let _ = handle(8, false);
}

建议运行:cargo run

期望输出:

acquire user=7
release user=7
acquire user=8
handle ok
release user=8

结合场景再看三个关注点

  1. 正常与提前 Err 路径均观察到 release,不代表日志写入永不失败
  2. 无需 finally 样板(对比部分语言)
  3. 锁的 Guard 同一模式

核心概念与准确模型

pub trait Drop {
    fn drop(&mut self);
}
  • 不能显式调用 Drop::drop;用 std::mem::drop(value) 提前结束所有权
  • 局部变量通常按声明逆序析构;结构体先运行自身 Drop::drop,再按字段声明正序析构字段,二者不能混淆
  • Copy 类型不实现 Drop

设计动机

  • 异常/错误路径也要释放
  • 把清理与类型绑定,而不是靠程序员记忆
  • 零成本常见路径

边界与误区

  • 普通作用域退出、提前返回和 unwind 时会清理;abort、process::exit、mem::forget 或引用计数环等可跳过析构
  • 已在 panic 展开时,析构再次 panic 会导致中止;Drop 签名不能返回 Result,重要 flush/提交失败应由显式方法报告
  • 循环引用(Rc)可能导致无法 drop,需 Weak
  • 异步取消与 drop 交互需小心

[!warning] 常见误区:假设 drop 在任意时刻立刻回收 OS 资源 缓冲 flush 失败等边界要查具体类型文档。

工程实践

  1. 资源类型暴露 guard
  2. 析构逻辑保持简短无失败敏感
  3. 需要手动提前释放就 drop(guard)
  4. 与错误处理组合:成功路径与失败路径同一清理

本节总结

  • Drop = 析构钩子
  • RAII = 资源=所有权寿命
  • 错误路径同样安全清理

自测题

  1. 为什么 Copy 与 Drop 互斥?
  2. mem::drop 做什么?
参考答案
  1. Copy 暗示简单按位复制,不该有特殊清理。
  2. 按值接收并在函数内丢弃参数;非 Copy 值被移动。传入 Copy 值或引用只丢弃副本/引用,不会析构引用指向的对象。

延伸阅读与资料来源

资料类型支撑内容
The Book — Drop官方书Drop
std::ops::Drop标准库trait
RAII (cppreference 概念对照)概念RAII 思想
创建于 2026/7/15 更新于 2026/10/7
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本