【问题标题】:Why are printed memory addresses in Rust a mix of both 40-bit and 48-bit addresses?为什么在 Rust 中打印的内存地址是 40 位和 48 位地址的混合?
【发布时间】:2020-04-07 20:41:59
【问题描述】:

我试图了解 Rust 处理内存的方式,并且我有一个打印一些内存地址的小程序:

fn main() {
    let a = &&&5;
    let x = 1;
    println!(" {:p}", &x);
    println!(" {:p} \n {:p} \n {:p} \n {:p}", &&&a, &&a, &a, a);
}

这将打印以下内容(因不同的运行而异):

0x235d0ff61c
0x235d0ff710 
0x235d0ff728 
0x235d0ff610 
0x7ff793f4c310

这实际上是 40 位和 48 位地址的混合。为什么会有这种混合?另外,有人可以告诉我为什么地址 (2, 3, 4) 不在以 8 个字节分隔的位置(因为std::mem::size_of_val(&a) 给出 8)?我在具有 24GB RAM 的 AMD x-64 处理器 (Phenom || X4) 上运行 Windows 10。

【问题讨论】:

    标签: memory rust


    【解决方案1】:

    所有地址的大小都相同,Rust 只是不打印尾随的 0 位。

    实际的内存布局是你的操作系统的一个实现细节,但是a 打印一个与所有其他变量不同的内存区域的原因是,a 实际上存在于你加载的二进制文件中,因为它是编译器已经可以计算的值。所有其他变量都是在运行时计算并存在于堆栈中。

    编译结果见https://godbolt.org/z/kzSrDr

    .L__unnamed_4 包含值 5; .L__unnamed_5.L__unnamed_6.L__unnamed_1&5 &&5&&&5

    所以.L__unnamed_1 是您系统上的0x7ff793f4c310。而0x235d0ff??? 在您的堆栈中并在代码的红色和蓝色区域中计算。

    【讨论】:

      【解决方案2】:

      这实际上是 40 位和 48 位地址的混合。为什么会这样混合?

      这并不是真正的混合,Rust 只是不显示前导零。这实际上是关于操作系统在地址空间中映射程序的各个组件(数据、bss、堆和堆栈)的位置。

      另外,有人可以告诉我为什么地址 (2, 3, 4) 不在以 8 字节分隔的位置(因为 std::mem::size_of_val(&a) 给出 8)?

      因为println! 是一个宏,它会扩展为堆栈帧中的一堆内容,因此您的值不会在帧最终代码(https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5b812bf11e51461285f51f95dd79236b)中彼此相邻定义。尽管即使它们存在也不能保证编译器不会例如重用现在死掉的内存以节省帧大小。

      【讨论】:

        猜你喜欢
        • 2021-01-06
        • 2019-02-22
        • 2018-03-12
        • 2022-08-21
        • 2011-04-18
        • 1970-01-01
        • 1970-01-01
        • 2016-10-29
        • 1970-01-01
        相关资源
        最近更新 更多