跳转至

rust中的内存布局

笔记来源 rust死灵书: https://doc.rust-lang.org/nomicon/repr-rust.html

结构体的内存布局

复合结构的对齐方式等于其成员字段的对其属性最大的那个, 整个结构的尺寸是对齐属性的整数倍, 例如:

struct A {
    a: u8,
    b: u32,
    c: u16,
}
println!("struct A size: {}", std::mem::size_of::<A>());  // struct A size: 8

上方结构体对齐之后的状态:

struct A {
    a: u8,
    // padding [u8; 3]
    b: u32,
    c: u16,
    // padding [u8; 2]
}

很奇怪, 上方结构体的最大对其属性是 字段b, 为4个字节, 结构体有3个字段, 那么对齐之后该结构体大小为 12字节

原因在于, rust在内存对齐时, 可能会做出一些优化, 减少内存占用, 可能会做出如下优化, 较小的内存调整到了一个区块

调整之后的内存布局如下

struct A {
    a: u8,
    c: u16,
    // padding [u8; 1]
    b: u32,
}

枚举的内存布局

枚举相较于结构体稍微复杂一些, 枚举在内存对齐的时候有些时候更像是演变了一个结构体

enum Foo{
    A(u32),
    B(u32),
    C(u32),
    D(u64)
}
println!("enum Foo size: {}", std::mem::size_of::<Foo>());  // enum Foo size: 16

我们打印的出 Foo 类型在内存布局之后占用的大小为16, 而类型中, 最大的对齐属性为u64也就是8, 也就是填充 ABC等字段到8字节, 哪怕是优化到如下形式, 也要占用24字节, 如下:

enum Foo{
    A(u32),  // A 与 B 优化在一个区块, 占用8字节
    B(u32),
    C(u32),  // C 填充 4 个字节进行对齐之后占用8字节
    // padding [u8; 4]
    D(u64)
}

很明显, rust并没有这样做, 可能进行了如下优化,这里是可能, 是我这里 个人的猜测

struct Foo {
    data: u64, // 这里存放真正的数据可能是 u64 或者 u32
    tag: u8 or u64,   // 这里是目标类型 可能是 ABCD 的任一
}