我如何 运行 清理 Rust 库中的代码?
How can I run clean-up code in a Rust library?
我正在制作一个跨平台终端库。因为我的库更改了终端的状态,所以我需要在进程结束时恢复对终端所做的所有更改。我现在正在实现这个功能,并想办法最后如何恢复到原来的终端状态。
我以为程序启动时会初始化一个静态变量,程序结束时这个静态变量就会被销毁。由于我的静态变量是一个实现了 Drop
特性的结构,它会在程序结束时被删除,但事实并非如此,因为字符串 "drop called" 从未被打印:
static mut SOME_STATIC_VARIABLE: SomeStruct = SomeStruct { some_value: None };
struct SomeStruct {
pub some_value: Option<i32>,
}
impl Drop for SomeStruct {
fn drop(&mut self) {
println!("drop called");
}
}
为什么程序结束时没有调用drop()
?我的想法错了吗,我应该换一种方式吗?
Rust 的原则之一是 no life before main,这意味着 在 main 之后没有生命。
在 main 之前或之后正确排序构造函数和析构函数存在相当大的挑战。在 C++ 中,这种情况被称为 static initialization order fiasco,虽然它有变通方法,但它的附属物(静态销毁命令惨败)有 none.
在 Rust 中,'static
生命周期加剧了挑战:运行在静态中使用析构函数可能导致观察到部分破坏的 other 静态。这是不安全的。
为了允许安全销毁静态变量,该语言需要引入 'static
生命周期的子集来排序静态变量的 construction/destruction,同时让这些生命周期仍然是 'static
里面 main
...
如何在程序的start/end处运行编码?
只需在 main
的 start/end 处 运行 编码。请注意,在 main
开头构建的任何结构都将按照相反的构建顺序在其末尾删除。
如果我不是自己写main
?
问 main
的作者,很好。
在库中强制执行初始化和清理代码的一种方法是引入只能用 public new()
函数构造的 Context
类型,并实现Drop
特质。库中每个需要初始化的函数都可以接受一个 Context
作为参数,因此用户需要在调用这些函数之前创建一个。任何清理代码都可以包含在 Context::drop()
.
中
pub struct Context {
// private field to enforce use of Context::new()
some_value: Option<i32>,
}
impl Context {
pub fn new() -> Context {
// Add initialization code here.
Context { some_value: Some(42) }
}
}
impl Drop for Context {
fn drop(&mut self) {
// Add cleanup code here
println!("Context dropped");
}
}
// The type system will statically enforce that the initialization
// code in Context::new() is called before this function, and the
// cleanup code in drop() when the context goes out of scope.
pub fn some_function(_ctx: &Context, some_arg: i32) {
println!("some_function called with argument {}", some_arg);
}
我正在制作一个跨平台终端库。因为我的库更改了终端的状态,所以我需要在进程结束时恢复对终端所做的所有更改。我现在正在实现这个功能,并想办法最后如何恢复到原来的终端状态。
我以为程序启动时会初始化一个静态变量,程序结束时这个静态变量就会被销毁。由于我的静态变量是一个实现了 Drop
特性的结构,它会在程序结束时被删除,但事实并非如此,因为字符串 "drop called" 从未被打印:
static mut SOME_STATIC_VARIABLE: SomeStruct = SomeStruct { some_value: None };
struct SomeStruct {
pub some_value: Option<i32>,
}
impl Drop for SomeStruct {
fn drop(&mut self) {
println!("drop called");
}
}
为什么程序结束时没有调用drop()
?我的想法错了吗,我应该换一种方式吗?
Rust 的原则之一是 no life before main,这意味着 在 main 之后没有生命。
在 main 之前或之后正确排序构造函数和析构函数存在相当大的挑战。在 C++ 中,这种情况被称为 static initialization order fiasco,虽然它有变通方法,但它的附属物(静态销毁命令惨败)有 none.
在 Rust 中,'static
生命周期加剧了挑战:运行在静态中使用析构函数可能导致观察到部分破坏的 other 静态。这是不安全的。
为了允许安全销毁静态变量,该语言需要引入 'static
生命周期的子集来排序静态变量的 construction/destruction,同时让这些生命周期仍然是 'static
里面 main
...
如何在程序的start/end处运行编码?
只需在 main
的 start/end 处 运行 编码。请注意,在 main
开头构建的任何结构都将按照相反的构建顺序在其末尾删除。
如果我不是自己写main
?
问 main
的作者,很好。
在库中强制执行初始化和清理代码的一种方法是引入只能用 public new()
函数构造的 Context
类型,并实现Drop
特质。库中每个需要初始化的函数都可以接受一个 Context
作为参数,因此用户需要在调用这些函数之前创建一个。任何清理代码都可以包含在 Context::drop()
.
pub struct Context {
// private field to enforce use of Context::new()
some_value: Option<i32>,
}
impl Context {
pub fn new() -> Context {
// Add initialization code here.
Context { some_value: Some(42) }
}
}
impl Drop for Context {
fn drop(&mut self) {
// Add cleanup code here
println!("Context dropped");
}
}
// The type system will statically enforce that the initialization
// code in Context::new() is called before this function, and the
// cleanup code in drop() when the context goes out of scope.
pub fn some_function(_ctx: &Context, some_arg: i32) {
println!("some_function called with argument {}", some_arg);
}