在询问我应该如何在FFI边界释放内存之后,Rust reddit上的某个人建议我不是将我的结构包装在一个结构中Box,而是可以使用Vec::from_raw_parts从以下结构构造一个向量,并且可以安全地删除它:
#[repr(C)]
pub struct Array {
data: *const c_void,
len: libc::size_t,
}
Run Code Online (Sandbox Code Playgroud)
但是,from_raw_parts似乎需要*mut _数据,所以我不知道如何继续......
答案非常简短self.data as *mut u8.但是,让我们谈谈更多细节......
首先,警告的话:
千万不能使用Vec::from_raw_parts,除非指针从来到Vec原本.有没有保证,一个任意的指针将是一个兼容的Vec,你很可能,如果你继续创建程序中的巨大漏洞.
不要不释放,你没有自己的指针.这样做会导致双重释放,这将会破坏程序中的其他大洞.
在重构之前,您需要知道向量的容量.您的示例结构只包含一个len.只有在len和capacity平等时才能接受.
现在,让我们看看我是否可以遵循自己的规则......
extern crate libc;
use std::mem;
#[repr(C)]
pub struct Array {
data: *const libc::c_void,
len: libc::size_t,
}
// Note that both of these methods should probably be implementations
// of the `From` trait to allow them to participate in more places.
impl Array {
fn from_vec(mut v: Vec<u8>) -> Array {
v.shrink_to_fit(); // ensure capacity == size
let a = Array {
data: v.as_ptr() as *const libc::c_void,
len: v.len(),
};
mem::forget(v);
a
}
fn into_vec(self) -> Vec<u8> {
unsafe { Vec::from_raw_parts(self.data as *mut u8, self.len, self.len) }
}
}
fn main() {
let v = vec![1, 2, 3];
let a = Array::from_vec(v);
let v = a.into_vec();
println!("{:?}", v);
}
Run Code Online (Sandbox Code Playgroud)
请注意,我们不必做任何明确的删除,Vec因为正常的Drop实现Vec发挥作用.我们必须确保我们Vec正确构建.