Không dễ như bạn muốn.
Phương thức phân bổ được hiển thị trong heap
module of the alloc
crate.
Tạo một số phương pháp wrapper và populating struct là thẳng về phía trước, nhưng chúng tôi nhanh chóng chạy vào một vấn đề:
#![feature(heap_api)]
extern crate libc;
extern crate alloc;
use libc::{c_void, c_uint};
use alloc::heap;
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Allocator {
alloc: Option<extern "C" fn(*mut c_void, c_uint) -> *mut c_void>,
free: Option<extern "C" fn(*mut c_void)>,
}
extern "C" fn alloc_ext(old: *mut c_void, size: c_uint) -> *mut c_void {
if old.is_null() {
heap::allocate(size as usize, align) as *mut c_void
} else {
heap::reallocate(old as *mut u8, old_size, size as usize, align) as *mut c_void
}
}
extern "C" fn free_ext(old: *mut c_void) {
heap::deallocate(old as *mut u8, old_size, align);
}
fn main() {
Allocator {
alloc: Some(alloc_ext),
free: Some(free_ext),
};
}
Các Rust cấp phát dự kiến sẽ được thông báo kích thước của bất kỳ phân bổ trước cũng như mong muốn căn chỉnh. API bạn đang đối sánh không có bất kỳ cách nào để truyền dữ liệu đó.
Căn chỉnh nên (Tôi không phải là chuyên gia) được phép mã hóa ở một số giá trị, nói 16 byte. Kích thước là phức tạp hơn. Bạn có thể sẽ cần phải ăn cắp một số thủ thuật C cũ và phân bổ thêm một chút không gian để lưu trữ kích thước. Bạn có thể lưu trữ kích thước và trả về một con trỏ vừa qua.
Một hoàn toàn chưa được kiểm tra dụ:
#![feature(alloc, heap_api)]
extern crate libc;
extern crate alloc;
use libc::{c_void, c_uint};
use alloc::heap;
use std::{mem, ptr};
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Allocator {
alloc: Option<extern "C" fn(*mut c_void, c_uint) -> *mut c_void>,
free: Option<extern "C" fn(*mut c_void)>,
}
const ALIGNMENT: usize = 16;
extern "C" fn alloc_ext(old: *mut c_void, size: c_uint) -> *mut c_void {
unsafe {
// Should check for integer overflow
let size_size = mem::size_of::<usize>();
let size = size as usize + size_size;
let memory = if old.is_null() {
heap::allocate(size, ALIGNMENT)
} else {
let old = old as *mut u8;
let old = old.offset(-(size_size as isize));
let old_size = *(old as *const usize);
heap::reallocate(old, old_size, size, ALIGNMENT)
};
*(memory as *mut usize) = size;
memory.offset(size_size as isize) as *mut c_void
}
}
extern "C" fn free_ext(old: *mut c_void) {
if old.is_null() { return }
unsafe {
let size_size = mem::size_of::<usize>();
let old = old as *mut u8;
let old = old.offset(-(size_size as isize));
let old_size = *(old as *const usize);
heap::deallocate(old as *mut u8, old_size, ALIGNMENT);
}
}
fn main() {
Allocator {
alloc: Some(alloc_ext),
free: Some(free_ext),
};
let pointer = alloc_ext(ptr::null_mut(), 54);
let pointer = alloc_ext(pointer, 105);
free_ext(pointer);
}
Không phải là [... using Vec
as an allocator ...] giải pháp cấp cao hơn?
Điều đó chắc chắn có thể, nhưng tôi không hoàn toàn chắc chắn nó sẽ hoạt động như thế nào với phân bổ lại. Bạn cũng sẽ phải theo dõi kích thước và dung lượng của Vec
để hoàn nguyên nó để tái phân bổ/thả nó.
https://www.reddit.com/r/rust/comments/2eqdg2/allocate_a_vec_on_cs_heap/ Có một số suy nghĩ về một chủ đề tương tự, mặc dù việc quản lý thời gian phân bổ có thể khó khăn. – snuk182
Như bạn chỉ ra, chủ đề đó là làm cho Rust sử dụng cùng một trình cấp phát như C. Có thể với [các trình phân bổ tùy chỉnh] (https://doc.rust-lang.org/stable/book/custom-allocators.html). – Shepmaster