我是一个全新的生 rust ,但有经验的C和我有这个生 rust 的代码不编译。
use std::fs;
static mut GRAPH_BUILDER: Option<Box<[&[u8]; 2]>> = None;
#[export_name = "wizer.initialize"]
pub extern "C" fn init() {
let weights = fs::read("./mobilenet.bin").unwrap();
let xml = fs::read_to_string("./mobilenet.xml").unwrap().into_bytes();
let input: [&[u8]; 2] = [&weights, &xml];
unsafe {
GRAPH_BUILDER = Some(Box::new(input));
}
}
pub fn main() {
unsafe {
if GRAPH_BUILDER.is_none() {
init();
}
}
}
使用rustc main.rs
编译时,会产生以下错误
error[E0597]: `weights` does not live long enough
--> main.rs:9:30
|
9 | let input: [&[u8]; 2] = [&weights, &xml];
| ^^^^^^^^ borrowed value does not live long enough
...
12 | GRAPH_BUILDER = Some(Box::new(input));
| --------------- argument requires that `weights` is borrowed for `'static`
13 | }
14 | }
| - `weights` dropped here while still borrowed
error[E0597]: `xml` does not live long enough
--> main.rs:9:40
|
9 | let input: [&[u8]; 2] = [&weights, &xml];
| ^^^^ borrowed value does not live long enough
...
12 | GRAPH_BUILDER = Some(Box::new(input));
| --------------- argument requires that `xml` is borrowed for `'static`
13 | }
14 | }
| - `xml` dropped here while still borrowed
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.
我理解这个错误是因为weights
存储在堆栈上,当init
函数终止时,它将被取消分配,所以静态GRAPH_BUILDER
将包含一个指向未分配内存的指针。所以我尝试使用Box
来代替,从我的理解应该像C中的malloc一样。但它似乎不起作用。我如何让rust在堆上分配weights
和xml
变量,而不知道它们在编译时的大小?即,malloc的rust等价物是什么?
我读过here,你可以调用clone
来解决这个问题。但我不想这样做,因为我读入的文件很大。而且我也不明白为什么这会解决这个问题。克隆不会也在堆栈上结束吗?
EDIT:还有一件重要的事情需要提一下,我需要给wasi_nn::load函数提供一个参数GRAPH_BUILDER
,它本质上期望它的数据类型是slice &[&[u8]]
。但是我完全不知道如何将它转换成这个数据类型。下面是main函数的延续。
use wasi_nn;
pub extern "C" fn main() {
bench::start();
let context: wasi_nn::GraphExecutionContext;
unsafe {
if GRAPH_BUILDER.is_none() {
init();
}
}
let graph = unsafe {
wasi_nn::load(
&GRAPH_BUILDER.expect("Graph builder was not initialized"),
wasi_nn::GRAPH_ENCODING_OPENVINO,
wasi_nn::EXECUTION_TARGET_CPU,
)
.unwrap()
};
我试图修改这段代码,使其在初始化函数中创建&[&xml.into_bytes(), &weights]
,而不是直接传递它。
1条答案
按热度按时间sqxo8psd1#
malloc的rust等价物是什么?
这是一个完全不必要的问题,你不需要进一步挖掘,你需要真正看看你的代码,想想发生了什么。
Rust的
&T
不是一个C风格的野生指针,它是一个字典范围的借用智能指针。它只能引用在其整个生命周期内 * 字典 * 有效的数据。所以我尝试使用Box来代替,从我的理解来看,它应该像C中的malloc一样。
当然不是,因为在你的盒子里,你仍然在放 * 对函数本地数据的引用 *。这正是Rust所抱怨的。
你并没有将数据复制或移动到堆中,你只是为同一个问题添加了一个间接地址:当函数结束时,
weights
和xml
仍然会被删除,而你放在Box
中的引用仍然会悬空,这是Rust不允许的。但是
weights
和xml
是Vec<u8>
,所以它们已经是拥有的,堆分配的数据类型。你所需要做的就是将它们移动到你的东西中:同样,你想在
extern C
函数中执行unwrap
的次数甚至比在Rust函数中更少。据我所知,最好的情况下,这将立即中止,最坏的情况下,它是UB。