我有一个存储我的对象的全局结构,并且具有复杂的行为。 除了数据之外,它还有一个用于对象的全局id生成器。他们也需要他们的工作。
use std::sync::{Arc, Mutex};
static mut system_ptr: *mut Box<System> = 0 as *mut Box<System>;
struct System {
data: Vec<Data>,
id_mutex: Arc<Mutex<u32>>,
}
impl System {
fn get_new_id() -> u32 {
unsafe {
let s = &mut *system_ptr;
let mut data = s.id_mutex.lock().unwrap();
*data += 1;
*data
}
}
}
我现在正在初始化这个结构:
fn main() {
let s = System{data: Vec::new(), id_mutex: Arc::new(Mutex::new(0 as u32))};
let mut s_box = Box::new(s);
unsafe {
system_ptr = &mut s_box as *mut Box<System>;
}
// here I have some work with the initialized "System"
}
当我将初始化代码从main()
移动到某个函数时,Box
被删除,我有一个“免费使用后”错误和崩溃。
我曾尝试使用&'static
但是目前还没有使用Rust的语义,或者说它不是很好。
无论如何,如何将某些Box
'内存(原始指针)的初始化移动到函数或方法?
编辑:这不是关于单身人士的问题,而是关于任何堆变量的初始化。马特,谢谢你的正确理解!
答案 0 :(得分:3)
您可以使用lazy_static包来初始化静态变量,然后您就不需要处理原始指针了。
但如果您确实想自己处理,可以这样做:
static mut system_ptr: *mut System = 0 as *mut System;
fn init() {
let mut system = Box::new(System(Vec::new()));
unsafe {
system_ptr = &mut *system;
}
std::mem::forget(system);
}
将框传递给std::mem::forget
故意泄漏它,确保其析构函数永远不会运行。我们不是存储指向Box的指针(它本身只是本地堆栈变量中的指针),而是直接将指针存储到堆上的值。
即将发布的Rust 1.4版本将具有Box::into_raw
功能,可以为您处理所有这些问题。如果您升级到Rust 1.4(目前在测试版频道上),您可以用以下代码替换上面的代码:
fn init() {
unsafe {
system_ptr = Box::into_raw(Box::new(System(Vec::new())));
}
}