Rust中一般通过syscall分配内存, 可以自定义分配内存算法,实现GlobalAlloc trait, 并通过#[global_allocator]注解告诉编译器自定义的内存分配算法。
alloc和Layout实战
在我们深入了解之前,先通过以下简单代码段对 alloc, dealloc 以及Layout对Rust内存分配有一个基本概念。
use std::alloc::{
alloc, dealloc, Layout};
fn main(){
let layout = Layout::new::<i32>();
let ptr = unsafe {
alloc(layout) } as *mut i32;
unsafe {
*ptr = 42;
}
let value = unsafe {
*ptr };
println!("value: {}", value);
unsafe {
dealloc(ptr as *mut u8, layout);
}
}
下面我们对这段代码做一个解释, 看看每行代码都做了那些事情。
let layout = Layout::new::<i32>();
这行代码就像是我们预先请求了一段新的数据存储单元, 通过Layout告诉Rust我们需要一段足够大的内存来存储i32, 你也可以换成其他数据类型比如:String,Structs等等,Rust会恰到好处的处理所需的存储单元大小。let ptr = unsafe { alloc(layout) } as *mut i32 ;
在这里我们通过调用std::alloc::alloc这个函数, 传入我们请求的内存布局, Rust会分配一块内存单元并返回这块内存的可变的i32指针 (*mut i32), 后面我们可以通过这个可变指针来修改或读取指针指向的数据.
这里使用了
unsafe关键字来告诉Rust编译器在这段unsafe代码块中我们不在需要编译器来保证内存安全. 因此,内存安全完全由开发者自行控制,
-
let value = unsafe { *ptr };
这里我们通过unsafe代码块来访问指针指向的内存空间. 但是需要注意的是指针指向的内存空间是没有安全保障的, 可能为null, 可以通过is_null()判断. 之后打印了指针指向的value. -
unsafe { dealloc(ptr as *mut u8, layout) };
通过dealloc方法释放之前申请的分配好的内存. 这里使用的mut u8指针类型来释放内存 而不是mut i32, 因为i32是申请的数据类型,也可以是String, 自定义的结构体等.
自定义Vec
Rust中的动态数组是通过NonNull智能指针, 并通过Layout::array来实现指针数组.
#![feature(allocator_api)]
use std::{
alloc::Layout, ptr::NonNull};
struct Arr<T: Sized> {
// 数据指针
ptr: NonNull<T>,
// 数组实际长度
len: usize,
// 数组容量
cap: usize,
}
impl<T

博客围绕Rust展开,介绍了Rust中内存分配方式,可自定义内存分配算法并通过注解告知编译器。通过代码展示alloc和Layout的使用,解释了请求内存、分配内存、访问内存及释放内存的操作。还阐述了Rust中通过NonNull智能指针和Layout::array实现自定义Vec的方法。
最低0.47元/天 解锁文章
47

被折叠的 条评论
为什么被折叠?



