68、内存泄漏
泄露数据
向生成的线程传递引用的主要问题是use-after-freebug:使用已经freed或de-allocated的指针访问数据。
如果我们使用的是堆分配的内存,我们可以通过告诉Rust永远不会回收该内存来避免这个问题:我们故意选择内存泄漏。
例如,可以使用 Rust 标准库中的 Box::leak 方法来做到这一点:
// 在堆上分配一个 `u32` ,将其封装在一个 `Box` 中。
let x = Box::new(41u32);
// 告诉 Rust,你永远不会释放该堆分配
// 使用 `Box::leak`。这样,我们就可以得到一个 "静态引用"。
let static_ref: &'static mut u32 = Box::leak(x);
数据泄露仅限于当前范围内
泄漏数据是很危险的:如果不断泄漏内存,最终会耗尽内存,并因内存不足错误而崩溃。
// 如果让它运行一段时间、
// 最终会耗尽所有可用内存。
fn oom_trigger() {
loop {
let v: Vec<usize> = Vec::with_capacity(1024);
v.leak();
}
}
同时,通过leak方法泄露的内存并不会被真正遗忘。
操作系统可以将每个内存区域映射到负责该区域的进程。当进程退出时,操作系统将收回该内存。
考虑到这一点,在以下情况下泄露内存是没有问题的:
- 需要泄漏的内存量是有边界的/预先知道的
- 你的进程持续时间很短,而且你确信不会在进程退出前耗尽所有可用内存
如果你的用例允许,"让操作系统来处理 "是一种完全有效的内存管理策略。
练习
// TODO: Given a vector of integers, leak its heap allocation.
// Then split the resulting static slice into two halves and
// sum each half in a separate thread.
// Hint: check out `Vec::leak`.
// TODO: 给定一个整数向量,泄漏其堆分配。
// 然后将生成的静态切片分成两半,并在单独的线程中对每一半进行求和。
// 在一个单独的线程中对每一半求和。
// 提示:查看 `Vec::leak`。
use std::thread;
pub fn sum(v: Vec<i32>) -> i32 {
let v = v.leak();//类似于创建一个静态引用
let mid = v.len() / 2;
let (v1, v2) = v.split_at(mid);//分出两个切片多线程计算和
let handle1 = thread::spawn(move || v1.into_iter().sum::<i32>());
let handle2 = thread::spawn(move || v2.into_iter().sum::<i32>());
handle1.join().unwrap() + handle2.join().unwrap()
}
好久没有在博客更新过Rust学习日记了,这很糟糕。最近这段时间也是挺忙的,去忙软考和学校迎新晚会的弹幕抽奖系统开发了,后面还会有期末考试和英语四级考试,唉,事情真多,要是大学没有这么多事情就好了。
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/11/13/68%e3%80%81%e5%86%85%e5%ad%98%e6%b3%84%e6%bc%8f.html
文章版权归作者所有,未经允许请勿转载。
THE END
