在询问我应该如何在FFI边界释放内存之后,Rust reddit上的某个人建议我不是将我的结构包装在一个结构中Box
,而是可以使用Vec::from_raw_parts
从以下结构构造一个向量,并且可以安全地删除它:
#[repr(C)] pub struct Array { data: *const c_void, len: libc::size_t, }
但是,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) -> 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 { 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); }
请注意,我们不必做任何明确的删除,Vec
因为正常的Drop
实现Vec
发挥作用.我们必须确保我们Vec
正确构建.