В close
вы заканчиваете тем, что создали Box<c_void>
вместо Box<Handle>
, потому что вы не бросили *mut c_void
обратно к *mut Handle
до вызова Box::from_raw
.
fn close(h: *mut c_void) {
let h = unsafe { Box::from_raw(h as *mut Handle) };
drop(h);
}
Кстати, Box
фактически не выделяет никакой памяти для типа нулевого размера (например, Handle
здесь) и вместо этого использует фиксированное ненулевое значение указателя (которое в текущей реализации являетсявыравнивание типа; по умолчанию тип с нулевым размером имеет выравнивание 1).Деструктор для упакованного типа нулевого размера знает, что он не пытается освободить память по этому фиктивному адресу памяти, но c_void
не является типом нулевого размера (он имеет размер 1), поэтому деструктор для Box<c_void>
пытается освободитьпамять по адресу 0x1
, которая вызывает ошибку.