I have the following structs
/// potentials
#[repr(C)]
pub struct Potential {
pub len: usize,
pub data: *const c_void,
pub scalar: ScalarType,
}
/// potentials
#[repr(C)]
pub struct Potentials {
pub n: usize,
pub data: *mut Potential,
pub scalar: ScalarType,
}
I’m creating some data using a function exposed to C via CFFI
let mut potentials = Vec::new();
unsafe {
if let Some(tmp) = (*fmm).potential(&leaf) {
for &p in tmp.iter() {
potentials.push(Potential {
len: p.len(),
data: p.as_ptr() as *const c_void,
scalar: ScalarType::F32,
})
}
} else {
nvecs = 0
}
}
let mut potentials = ManuallyDrop::new(potentials);
let potentials = Potentials {
n: nvecs,
data: potentials.as_mut_ptr(),
scalar: ScalarType::F32,
};
Box::into_raw(Box::new(potentials))
I don’t want the vector ‘potentials’ which I’m storing in the outer struct to be cleaned up by Rust, so I use Manually Drop.
I implemented drop on these two structs as
impl Drop for Potential {
fn drop(&mut self) {
let Self {
len,
data,
scalar
} = self;
match scalar {
ScalarType::F32 => {
let tmp = unsafe { Vec::from_raw_parts(*data as *mut f32, *len, *len) };
drop(tmp);
}
ScalarType::F64 => {
let tmp = unsafe { Vec::from_raw_parts(*data as *mut f64, *len, *len) };
drop(tmp)
}
ScalarType::C32 => {
let tmp = unsafe { Vec::from_raw_parts(*data as *mut c32, *len, *len) };
drop(tmp)
}
ScalarType::C64 => {
let tmp = unsafe { Vec::from_raw_parts(*data as *mut c64, *len, *len) };
drop(tmp)
}
}
}
}
impl Drop for Potentials {
fn drop(&mut self) {
let Self {
n,
data,
scalar: _
} = self;
unsafe {
let potentials = Vec::from_raw_parts(*data, self.n, self.n);
drop(potentials)
}
}
}
And call this from C using an exposed function
/// Free potentials
#[no_mangle]
pub extern "C" fn free_potentials(potentials_p: *mut Potentials) {
if !potentials_p.is_null() {
unsafe { drop(Box::from_raw(potentials_p)) }
}
}
However when running the free_potentials
function in an example code I keep getting an error that
demo(51650,0x1e06c9000) malloc: *** error for object 0x12813cd18: pointer being freed was not allocated
However, surely the pointer is being allocated as it’s being allocated by the exposed C function? I’m very confused, I thought that this code is allocating in Rust, passing ownership to C, and I was handling this by explicitly implementing Drop with ManuallyDrop.