深入 Rust 内存模型:从栈帧到堆分配
Rust 的所有权系统在语言层面保证了内存安全,但理解底层的内存布局对于编写高性能代码同样重要。本文从汇编层面深入分析 Rust 的内存模型。
栈帧布局分析:
struct Point {
x: f64,
y: f64,
}
fn process(p: Point) -> f64 {
p.x * p.x + p.y * p.y
}
// 编译后的汇编(x86_64)
// process:
// movsd xmm2, xmm0 ; x
// mulsd xmm2, xmm0 ; x * x
// movsd xmm3, xmm1 ; y
// mulsd xmm3, xmm1 ; y * y
// addsd xmm2, xmm3 ; x*x + y*y
// movapd xmm0, xmm2 ; 返回值
// ret
自定义全局分配器:
use std::alloc::{GlobalAlloc, Layout, System};
struct TrackingAllocator;
unsafe impl GlobalAlloc for TrackingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let ptr = System.alloc(layout);
if !ptr.is_null() {
// 记录分配信息
ALLOC_TRACKER.track(layout.size(), ptr);
}
ptr
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
ALLOC_TRACKER.untrack(ptr);
System.dealloc(ptr, layout);
}
}
#[global_allocator]
static GLOBAL: TrackingAllocator = TrackingAllocator;
Rust 的枚举在内存中的表示也值得深入研究。Option<Box<T>> 利用空指针优化,与裸指针占用相同的内存。而普通的 Option<&T> 同样利用引用的非空保证实现了零开销的 None 表示。理解这些底层细节,可以帮助你在性能敏感场景做出更好的数据结构选择。