如何在Rust库中运行清理代码?

Tim*_*ost 5 static destroy rust

我正在制作一个跨平台终端库.因为我的库改变了终端的状态,所以我需要恢复进程结束时对终端所做的所有更改.我现在正在实现此功能,并思考如何在最后恢复到原始终端状态的方法.

我认为在程序启动时初始化静态变量,并且当程序结束时,这个静态变量将被销毁.由于我的静态变量是一个已经实现了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");
    }
}
Run Code Online (Sandbox Code Playgroud)

drop()程序结束时为什么不调用?我的想法是错的,我应该采取另一种方式吗?

Mat*_* M. 6

Rust之一的原则之一就是在main之前没有生命,这意味着在主要之后没有生命.

在main之前或之后正确排序构造函数和析构函数存在相当大的挑战.在C++中,情况被称为静态初始化顺序fiasco,虽然有解决方法,但它的挂件(静态销毁顺序惨败)却没有.

在Rust中,'static生命中的挑战更加严重:在静力学中运行析构函数可能会导致观察到部分破坏的其他静力学.这是不安全的.

为了安全地破坏静力学,语言需要引入'static生命周期的子集来命令构造/破坏静力学,同时让生命仍然'static来自内部main......


如何在程序的开头/结尾运行代码?

只需在开始/结束时运行代码main.请注意,在开头构建的任何结构都main将以与构造相反的顺序在其末尾删除.

如果我不写main自己?

main很好地问作者.


Sve*_*ach 6

在库中强制初始化和清理代码的一种方法是引入一种Context只能用公共new()函数构造并实现Drop特征的类型.库中需要初始化的每个函数都可以使用Contextas参数,因此用户需要在调用这些函数之前创建一个函数.任何清理代码都可以包含在内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);
}
Run Code Online (Sandbox Code Playgroud)