如何在函数中初始化堆上的静态结构?
How to initialize static struct on heap in a function?
我有一个全局结构来存储我的对象并具有复杂的行为。
除了数据之外,它还有一个用于对象的全局 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
被丢弃,我遇到 "use after free" 错误和崩溃。
我尝试使用 &'static
但目前对 Rust 的语义还不够流利,或者这是个坏主意。
无论如何,如何将一些 Box
内存(原始指针)的初始化移动到函数或方法?
编辑:这不是关于单例的问题,而是关于任何堆变量的初始化。马特,感谢您的正确理解!
您可以使用 lazy_static crate 来初始化您的静态变量,然后您就不需要处理原始指针了。
但是如果你想自己处理,你可以这样做:
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(目前处于 beta 通道),你可以将上面的代码替换为:
fn init() {
unsafe {
system_ptr = Box::into_raw(Box::new(System(Vec::new())));
}
}
我有一个全局结构来存储我的对象并具有复杂的行为。 除了数据之外,它还有一个用于对象的全局 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
被丢弃,我遇到 "use after free" 错误和崩溃。
我尝试使用 &'static
但目前对 Rust 的语义还不够流利,或者这是个坏主意。
无论如何,如何将一些 Box
内存(原始指针)的初始化移动到函数或方法?
编辑:这不是关于单例的问题,而是关于任何堆变量的初始化。马特,感谢您的正确理解!
您可以使用 lazy_static crate 来初始化您的静态变量,然后您就不需要处理原始指针了。
但是如果你想自己处理,你可以这样做:
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(目前处于 beta 通道),你可以将上面的代码替换为:
fn init() {
unsafe {
system_ptr = Box::into_raw(Box::new(System(Vec::new())));
}
}