home / skills / huiali / rust-skills / rust-resource

rust-resource skill

/skills/rust-resource

This skill explains and optimizes Rust smart pointers and resource management with practical examples for Box, Rc, Arc, RefCell, and Drop.

npx playbooks add skill huiali/rust-skills --skill rust-resource

Review the files below or copy the command above to add this skill to your agents.

Files (4)
SKILL.md
3.2 KB
---
name: rust-resource
description: 智能指针与资源管理专家。处理 Box, Rc, Arc, Weak, RefCell, Cell, interior mutability, RAII, Drop, 堆分配, 引用计数, 智能指针--- # 智能指针与资源管理 ## 核心问题 **这个资源应该用什么方式管理?** 选择正确的智能指针是 Rust 编程的核心决策之一。
---


## 选择决策树

```
需要共享数据吗?
    │
    ├─ 否 → 单 owner
    │   ├─ 需要堆分配? → Box<T>
    │   └─ 栈上即可? → 直接值类型
    │
    └─ 是 → 需要共享
          │
          ├─ 单线程?
          │   ├─ 可变? → Rc<RefCell<T>>
          │   └─ 只读? → Rc<T>
          │
          └─ 多线程?
                ├─ 可变? → Arc<Mutex<T>> 或 Arc<RwLock<T>>
                └─ 只读? → Arc<T>
```


## 智能指针对比

| 类型 | 所有权 | 线程安全 | 适用场景 |
|-----|-------|---------|---------|
| `Box<T>` | 单 owner | Yes | 堆分配、递归类型、trait object |
| `Rc<T>` | 共享 | No | 单线程共享、避免 clone |
| `Arc<T>` | 共享 | Yes | 多线程共享、只读数据 |
| `Weak<T>` | 弱引用 | - | 打破循环引用 |
| `RefCell<T>` | 单 owner | No | 运行时借用检查 |
| `Cell<T>` | 单 owner | No | Copy 类型的内部可变性 |


## 常见错误与解决方案

### Rc 循环引用泄漏

```rust
// ❌ 内存泄漏:两个 Rc 互相引用
struct Node {
    value: i32,
    next: Option<Rc<Node>>,
}

// ✅ 解决方案:使用 Weak 打破循环
struct Node {
    value: i32,
    next: Option<Weak<Node>>,
}
```

### RefCell panic

```rust
// ❌ 运行时 panic:双重可变借用
let cell = RefCell::new(vec![1, 2, 3]);
let mut_borrow = cell.borrow_mut();
let another_borrow = cell.borrow(); // panic!

// ✅ 解决方案:使用 try_borrow
if let Ok(mut_borrow) = cell.try_borrow_mut() {
    // 安全使用
}
```

### Arc 开销投诉

```rust
// ❌ 不必要的 Arc:单线程环境
let shared = Arc::new(data);

// ✅ 单线程用 Rc
let shared = Rc::new(data);

// ❌ 多线程不必要的原子操作
// 如果确定不需要跨线程共享,就不要用 Arc
```


## 内部可变性选择

```rust
// T 是 Copy 类型 → Cell
struct Counter {
    count: Cell<u32>,
}

// T 不是 Copy → RefCell
struct Container {
    items: RefCell<Vec<Item>>,
}

// 多线程 → Mutex 或 RwLock
struct SharedContainer {
    items: Mutex<Vec<Item>>,
}
```


## RAII 与 Drop

```rust
struct File {
    handle: std::fs::File,
}

impl Drop for File {
    fn drop(&mut self) {
        // 自动释放资源
        println!("File closed");
    }
}

// 使用 guard pattern 确保清理
struct Guard<'a> {
    resource: &'a Resource,
}

impl Drop for Guard<'_> {
    fn drop(&mut self) {
        self.resource.release();
    }
}
```


## 性能提示

| 场景 | 建议 |
|-----|------|
| 大量小对象 | `Rc::make_mut()` 避免 clone |
| 频繁读取 | `RwLock` 比 `Mutex` 更好 |
| 计数器 | 用 `AtomicU64` 而非 `Mutex<u64>` |
| 缓存 | 考虑 `moka` 或 `cached` crate |


## 何时不用智能指针

- 栈上数据足够 → 用值类型
- 借用即可满足 → 用引用 `&T`
- 生命周期简单 → 不要过度抽象

Overview

This skill is an expert layer for Rust smart pointers and resource management. I provide clear decision guidance, common pitfalls and fixes, and performance-minded patterns for Box, Rc, Arc, Weak, RefCell, Cell, RAII and Drop. The goal is to help engineers choose the right pointer, avoid leaks and panics, and design safe, efficient ownership for real-world code.

How this skill works

I inspect ownership requirements (single owner vs shared), threading constraints (single-thread vs multi-thread), and mutability needs to recommend concrete pointer types and synchronization primitives. I detect common anti-patterns such as Rc cycles, RefCell double-borrows, unnecessary Arc usage, and suggest fixes like Weak, try_borrow, or switching to Rc. I also provide RAII/Drop guidance and micro-optimizations (e.g., RwLock vs Mutex, Atomic counters).

When to use it

  • Use Box<T> for single-owner heap allocation, recursive types, or trait objects.
  • Use Rc<T>/RefCell<T> for single-thread shared data with interior mutability at runtime.
  • Use Arc<T>/Arc<Mutex<T>> or Arc<RwLock<T>> for multi-thread shared data, choose locks based on read/write patterns.
  • Use Weak<T> to break reference cycles and avoid memory leaks with graph-like structures.
  • Use Cell<T> for interior mutability of Copy types and RefCell<T> for non-Copy types.
  • Prefer plain values or &T when stack allocation and borrow rules suffice.

Best practices

  • Start with the simplest option: plain value, &T, or Box<T> before adding shared pointers.
  • Break cycles with Weak to prevent Rc/Arc leaks in parent/child graphs.
  • Avoid RefCell panics by preferring try_borrow/_mut and by minimizing overlapping borrows.
  • Don’t use Arc in single-thread contexts; prefer Rc to avoid atomic overhead.
  • Choose RwLock for read-heavy workloads and Mutex for mostly-writes; use atomics for counters where possible.

Example use cases

  • Designing a tree/graph where children reference parents: use Rc for ownership and Weak for parent links.
  • Sharing a configuration object across threads: Arc<T> for read-only, Arc<RwLock<T>> for read-mostly updates.
  • Implementing a mutable shared cache in one thread: Rc<RefCell<HashMap<...>>> to allow interior mutability.
  • Managing OS resources with RAII: implement Drop to ensure file/handle cleanup and use guard patterns for scoped release.
  • Optimizing a hotspot: replace Mutex<u64> counters with AtomicU64 or use RwLock for heavy-read scenarios.

FAQ

How do I stop Rc causing memory leaks?

Replace one side of the strong reference with Weak so cycles can be collected when no strong references remain.

When will RefCell panic at runtime?

RefCell panics on violating borrow rules (e.g., an active mutable borrow while another borrow exists); use try_borrow/_mut to handle failure safely.