How to convert a *const pointer into a Vec to corr

2019-05-31 20:50发布

问题:

After asking how I should go about freeing memory across the FFI boundary, someone on the Rust reddit suggested that rather than wrapping my structs in a Box, I could use Vec::from_raw_parts to construct a vector from the following struct, and that this could be safely dropped:

#[repr(C)]
pub struct Array {
    data: *const c_void,
    len: libc::size_t,
}

However, from_raw_parts seems to require *mut _ data, so I'm not sure how to proceed…

回答1:

The very short answer is self.data as *mut u8. But, let's talk more details...

First, words of warning:

  1. Do not use Vec::from_raw_parts unless the pointer came from a Vec originally. There is no guarantee that an arbitrary pointer will be compatible with a Vec and you are likely to create giant holes in your program if you proceed.

  2. Do not free a pointer that you don't own. Doing so leads to double frees, which will blow other large holes in your program.

  3. You need to know the capacity of the vector before you can reconstruct it. Your example struct only contains a len. This is only acceptable if the len and capacity are equal.

Now, let's see if I can follow my own rules...

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

Note that we don't have to do any explicit dropping of the Vec because the normal Drop implementation of Vec comes into play. We just have to make sure that we construct a Vec properly.



标签: rust