我有以下rust代码:
pub struct Settings {
pub vec: Vec<usize>,
pub index: usize,
}
pub fn add_to_settings_vec(ptr: *mut Settings) {
// create a box from the pointer
let boxed_settings = unsafe { Box::from_raw(ptr) };
// get the value in the box
let mut settings = *boxed_settings;
// mutate the value
settings.vec.push(123);
// create a new box and get a raw pointer to it so the value isn't deallocated
Box::into_raw(Box::new(project));
}
我想确保作为函数参数传递的指针保持有效并指向修改后的Settings
值,即使在向未装箱的Settings
值的向量添加元素之后。
我想我需要以下步骤来实现我的目标:
- 接收到
Settings
的指针 - 打开
- 修改设置
- 确保
Settings
不被释放 - 现在我需要传入的指针仍然有效,并指向修改后的
Settings
这应该是可能的,因为Settings
值是固定大小,据我所知,即使是向量,因为向量在不同的位置增长其内存。
我已经看了https://doc.rust-lang.org/std/boxed/struct.Box.html上的文档,但我还没能弄清楚。
我也读过关于大头针,但我不知道如何或何时使用它们:https://doc.rust-lang.org/std/pin/index.html.
上面的代码是否总是保留传入的指针?我希望你能解释一下为什么或为什么不。
如果不是,我怎么能确保传入的指针保持有效,并继续指向修改的Settings
值,在内存中的同一位置?
Unbox value
就地修改设置
确保设置不会被取消分配
它已经在步骤(1)中被释放了:当你执行它时,你将Settings结构体移出了Box,并在这样做时释放了Box。
我不明白你为什么要经历这些混乱(或者为什么你把不安全的指针传递给一个安全的非外部函数)。
// create a box from the pointer
let mut settings = unsafe { Box::from_raw(ptr) };
// mutate the value
settings.vec.push(123);
settings.leak();
可以很好地工作,并且不会释放任何东西。虽然它仍然是有风险的,没有必要在Box
上得到一个句柄,如果指针只是借来的(这似乎是在这里,因为设置永远不会返回。
一个更好的方法是创建一个借用的设置vec:
let v = unsafe { &mut (*ptr).vec };
v.push(123);
如果还需要更新索引,也可以使用settings结构体:
let settings = unsafe { &mut (*ptr) };
settings.vec.push(123);
您可以通过解引用不安全块中的指针来实现突变:
pub struct Settings {
pub vec: Vec<usize>,
pub index: usize,
}
pub fn add_to_settings_vec(ptr: *mut Settings) {
// mutate the value
unsafe {(*ptr).vec.push(123)};
}
fn main() {
let mut s = Settings {
vec: vec![],
index: 10,
};
add_to_settings_vec(&mut s as *mut Settings);
println!("{:?}", s.vec);
}
游乐场