memory-management - 为什么第二个变量的地址不在第一个变量之后?

标签 memory-management rust memory-layout

我知道在 64 位系统上,Vec 将存储指向堆的 8 字节指针,8 字节用于容量,8 字节用于长度。

我假设a的地址紧跟在v的地址之后,但是当我检查堆栈上向量分配的边界时,我发现它总是占用 31 个字节的堆栈内存,比它应该多 7 个字节。字符串也是如此。

pub fn main() {
    let v = vec![1_u8];
    let a = 1_u8;

    let v_raw = &v as *const _;
    let a_raw = &a as *const _;

    println!("v addr = {:p}, dec = {}", v_raw, v_raw as usize);
    println!("a addr = {:p}, dec = {}", a_raw, a_raw as usize);
    println!("offset = {} bytes", a_raw as usize - v_raw as usize);

    // changing below 3 print will affect the mysterious 7 bytes
    //    println!("v_raw addr = {:p}", &v_raw);     // (1)
    //    println!("a_raw addr = {:p}", &a_raw);     // (2)
    println!("v as_ptr = {:p}", v.as_ptr()); // (3)

    // dereference through offset 24 to 30 -> 7 bytes
    let mut offset = 24_usize;
    loop {
        if offset == 31 {
            break;
        }

        // usize to *const usize(raw pointer)
        let mut addr = (v_raw as usize + offset) as *const usize;
        let deref_value = unsafe { *addr as u8 };

        println!(
            "offset = {}, addr = {:p}, value hex = {:x}, value = {}",
            offset, addr, deref_value, deref_value
        );

        offset += 1;
    }
}
v addr = 0x7fffbcf48b70, dec = 140736363531120
a addr = 0x7fffbcf48b8f, dec = 140736363531151
offset = 31 bytes
v as_ptr = 0x55d9c823ea40
offset = 24, addr = 0x7fffbcf48b88, value hex = 0, value = 0
offset = 25, addr = 0x7fffbcf48b89, value hex = 0, value = 0
offset = 26, addr = 0x7fffbcf48b8a, value hex = 0, value = 0
offset = 27, addr = 0x7fffbcf48b8b, value hex = 0, value = 0
offset = 28, addr = 0x7fffbcf48b8c, value hex = 0, value = 0
offset = 29, addr = 0x7fffbcf48b8d, value hex = 0, value = 0
offset = 30, addr = 0x7fffbcf48b8e, value hex = 0, value = 0

有时这 7 个额外地址包含所有 0 值,有时如果我取消注释所有标记为 (1)(2)(3)

println! 宏则不会

当我依次声明 va 时,我期望 av 旁边堆栈,那么为什么我要额外获得这 7 个字节?这个额外的内存是为一些特殊的东西设计的吗?

最佳答案

I assume that the address of a is right after the address of v.

仅仅因为你按这个顺序写了这些变量并不意味着 Rust 会把它们连续地存储在堆栈上。 Rust 编译器可以自由地将东西放在内存中它认为合适的地方,你绝对不能依赖顺序。最终顺序可能会有所不同,具体取决于:

  • Rust 编译器的版本
  • 如果您是为调试或发布而编译
  • 目标操作系统
  • objective-c PU 架构
  • 您应用程序中附近的其他代码

Vec 的实际大小可以显示为 24:

let v = vec![1_u8];
println!("size = {}", std::mem::size_of_val(&v)); // size = 24

另见:

关于memory-management - 为什么第二个变量的地址不在第一个变量之后?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56973256/

相关文章:

c - 为什么 free 不清除指针值?

rust - 我如何对改变设置数据的代码进行基准测试?

error-handling - 如何在没有空的匹配臂的情况下检索结果的错误值? [复制]

c++ - 为什么 sizeof(Derived4) 是 8 字节?我觉得应该是5个字节

c++ - 多重虚拟继承中的虚拟表和内存布局

c - 捆绑 Malloc 调用

c - CPU如何从内存中读取数据?缓存如何发挥重要作用

c++ - 内存重新对齐后重新对齐指针

fortran - 对 `_gfortran_cpu_time_4' 的 undefined reference

c++ - 将 POD 结构转换为派生类型