如何在函数中初始化堆上的静态结构?

时间:2015-10-11 21:03:09

标签: memory-management rust heap-memory

我有一个存储我的对象的全局结构,并且具有复杂的行为。 除了数据之外,它还有一个用于对象的全局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'内存(原始指针)的初始化移动到函数或方法?

编辑:这不是关于单身人士的问题,而是关于任何堆变量的初始化。马特,谢谢你的正确理解!

1 个答案:

答案 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())));
    }
}