mem::ManuallyDrop 类与 mem::forget() 函数
ManuallyDropT 的析构函数 (基于 Drop trait 实现的).
可以用它来调整结构体中成员的 drop 顺序.
看下面一个例子:
use std::mem::ManuallyDrop;
pub struct Sheep {
name: String,
}
pub struct Cow {
name: String,
}
pub struct Horse {
name: String,
}
impl Drop for Sheep {
fn drop(&mut self) {
println!("Dropping sheep {}", self.name);
}
}
impl Drop for Cow {
fn drop(&mut self) {
println!("Dropping cow {}", self.name);
}
}
impl Drop for Horse {
fn drop(&mut self) {
println!("Dropping horse {}", self.name);
}
}
pub struct Animals {
sheep: ManuallyDrop<Sheep>,
#[allow(dead_code)]
horse: Horse,
cow: ManuallyDrop<Cow>,
}
impl Drop for Animals {
fn drop(&mut self) {
println!("Dropping animals");
unsafe {
// 手动调用 `drop()` 释放这两个对象.
ManuallyDrop::drop(&mut self.sheep);
ManuallyDrop::drop(&mut self.cow);
// 而 horse 对象会被自动释放.
}
}
}
#[allow(unused_variables)]
fn main() {
let animals = Animals {
sheep: ManuallyDrop::new(Sheep {
name: "Doly".to_owned(),
}),
horse: Horse {
name: "Tom".to_owned(),
},
cow: ManuallyDrop::new(Cow {
name: "Jery".to_owned(),
}),
};
// 使用 mem::forget() 会导致内存泄露
//mem::forget(animals);
}
查看上面例子的打印日志, 可以发现结构体 Animals 的析构顺序是:
- Animals
- Sheep
- Cow
- Horse
而下面的代码是结构体的一般写法, 其析构顺序是:
- Animals
- Sheep
- Horse
- Cow
struct Animals {
sheep: Sheep,
horse: Horse,
cow: Cow,
}
mem::forget() 函数
forget() 函数就是利用了 ManuallyDrop 类, 看看该函数的实现:
pub const fn forget<T>(t: T) {
let _ = ManuallyDrop::new(t);
}
不正确的使用 forget() 函数会产生内存泄露, 看一个例子:
use std::mem;
fn main() {
let msg = String::from("Hello, Rust");
mem::forget(msg);
// msg 的堆内存没有被释放, 产生了内存泄露
}