序言
Rust 以其内存安全性而闻名。虽然在 Rust 中创建内存泄漏并不容易,但是需要清楚,"无内存泄漏"并不是 Rust 提供的安全保证的一部分。
实际上,在系统编程语言中,有时候你需要允许内存泄漏。以 FFI 为例,如果你的资源在被另一种语言使用后被释放,那就产生了问题。
本文将探究,什么样的操作会在 Rust 中引起内存泄露,我们又该通过什么方式来检测出 Rust 程序的内存泄露问题。
如何引起内存泄露
在 Rust 程序中,以下操作可能导致内存泄漏:
- 调用
std::mem::forget
函数。 - 创建循环引用的
Rc
指针:
若在
Rc
指针之间形成循环,这将导致内存永久无法释放。为了打破循环,你可以使用Weak
指针。举例来说,假设我们有一棵树,在父节点到子节点的连接中,我们可以使用强Rc
指针,而在子节点到父节点的连接上,我们可以使用Weak
指针。
- 使用
Box::leak
创建静态引用。 - 在 FFI 情况下使用
Box::into_raw
。
如何检测出内存泄露问题
LeakSanitizer
LeakSanitizer 是由 LLVM 项目提供的一个开源工具,它是一个独立的运行时库,目的是检测进程的内存泄漏问题。
当 LeakSanitizer 检测到可能的内存泄漏时,它会生成一份详细报告,包含泄露类型以及泄漏发生的位置。这在排查内存泄漏问题时相当有用。
你可以通过使用 -Z sanitizer=leak
选项在编译和运行时启用 LeakSanitizer:
ini
RUSTFLAGS="-Z sanitizer=leak" cargo +nightly run
这样 Rust 就会打开 LeakSanitizer 并在运行程序时对内存泄漏进行检测。
请注意,LeakSanitizer 目前仅适用于 x86_64 Linux 和 x86_64 macOS。
Valgrind
首先,你需要安装 Valgrind。但需要注意的是,Valgrind 目前还不支持 M1/M2 的 Mac 系统。
在终端中输入以下的命令来运行 Valgrind:
bash
valgrind --leak-check=full target/debug/your_program
这个命令将会启动 Valgrind,并使用 --leak-check=full
选项来对 your_program
运行全面的内存泄漏检查。