Могу ли я создать Vec
, который становится владельцем базовой памяти, которая освобождается при освобождении Vec
?
Не безопасно, нет.Вы не должны использовать Vec::from_raw_parts
, если указатель не исходил из Vec
изначально (ну, из того же распределителя памяти).В противном случае вы попытаетесь освободить память, о которой ваш распределитель не знает;очень плохая идея.
где / как в Rust я должен освободить память, выделенную функцией C?
Как только вы закончите с этим и не раньше.
что-нибудь из вышеперечисленного, что можно / нужно улучшить?
- Нет необходимости приводить указатель при вызове
slice::from_raw_parts
- Нет необходимости явно указывать типы переменных
- Использовать
ptr::null
, а не ptr::null_mut
- Выполнить проверку указателя NULL
- Проверить, что длина неотрицательный
use std::{ptr, slice};
extern "C" {
fn allocate_data(data_ptr: *mut *const f32, data_len: *mut i32);
fn deallocate_data(data_ptr: *const f32);
}
fn get_vec() -> Vec<f32> {
let mut data_ptr = ptr::null();
let mut data_len = 0;
unsafe {
allocate_data(&mut data_ptr, &mut data_len);
assert!(!data_ptr.is_null());
assert!(data_len >= 0);
let v = slice::from_raw_parts(data_ptr, data_len as usize).to_vec();
deallocate_data(data_ptr);
v
}
}
fn main() {}
Вы не указали, почему он должен быть Vec
, но если вам никогда не нужно изменять размер, вы можете создать свой собственный тип, который можетбыть разыменованным как фрагмент и удаляет данные, когда это необходимо:
use std::{ptr, slice};
extern "C" {
fn allocate_data(data_ptr: *mut *const f32, data_len: *mut i32);
fn deallocate_data(data_ptr: *const f32);
}
struct CVec {
ptr: *const f32,
len: usize,
}
impl std::ops::Deref for CVec {
type Target = [f32];
fn deref(&self) -> &[f32] {
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
impl Drop for CVec {
fn drop(&mut self) {
unsafe { deallocate_data(self.ptr) };
}
}
fn get_vec() -> CVec {
let mut ptr = ptr::null();
let mut len = 0;
unsafe {
allocate_data(&mut ptr, &mut len);
assert!(!ptr.is_null());
assert!(len >= 0);
CVec {
ptr,
len: len as usize,
}
}
}
fn main() {}
См. также: