如何将* const指针转换为Vec以正确删除它?

时间:2016-01-05 22:10:42

标签: rust

asking之后我应该如何在FFI边界上释放内存,Rust reddit上的某个人建议我可以使用Entity而不是将我的结构包装在Box中。从以下结构构造一个向量,并且可以安全地删除它:

Vec::from_raw_parts

但是,#[repr(C)] pub struct Array { data: *const c_void, len: libc::size_t, } 似乎需要from_raw_parts数据,因此我不确定如何继续...

1 个答案:

答案 0 :(得分:9)

答案非常简短self.data as *mut u8。但是,让我们谈谈更多细节......

首先,警告的话:

  1. 使用Vec::from_raw_parts,除非指针最初来自Vec无保证任意指针与Vec兼容,如果继续,您可能会在程序中创建巨大漏洞。

  2. 释放您不拥有的指针。这样做会导致双重释放,这将会破坏程序中的其他大洞。

  3. 需要了解向量的容量,然后才能重新构建它。您的示例结构只包含len。只有lencapacity相等时,才能接受此项。

  4. 现在,让我们看看我是否可以遵循自己的规则......

    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);
    }
    

    请注意,我们不必明确删除Vec,因为Drop的正常Vec实现正在发挥作用。我们必须确保正确构建Vec