为什么后续的Rust变量增加堆栈指针而不是减少堆栈指针? [英] Why do subsequent Rust variables increment the stack pointer instead of decrementing it?

查看:147
本文介绍了为什么后续的Rust变量增加堆栈指针而不是减少堆栈指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得奇怪的是,当您在Rust中创建静态分配的变量时,似乎随着堆栈指针的增加而增加.我知道不是这种情况,因为随着内存分配,堆栈指针减少了.

I find it odd how when you create statically-allocated variables in Rust that it seems as the stack pointer increases. I know this is not the case since the stack pointer decreases as memory is allocated.

如果我要用C做同样的事情,我会发现随着创建更多变量,堆栈指针会减少.

If I were to do the same thing in C, I would see the stack pointer decrease as I created more variables.

为什么会这样? Rust编译器是否将这些分配自下而上,而不是从上至下?

Why is it this way? Does the Rust compiler allocate these from bottom to top instead on top to bottom?

fn main() {
    let i1 = 1;
    let i2 = 1;
    let i3 = 1;
    println!("i1 : {:?}", &i1 as *const i32);
    println!("i2 : {:?}", &i2 as *const i32);
    println!("i3 : {:?}", &i3 as *const i32);
}

当我运行该程序时,会收到以下消息:

When i run this program, I receive this:

i1 : 0x9f4f99fb24
i2 : 0x9f4f99fb28
i3 : 0x9f4f99fb2c

如果我使用C,我会得到这个:

If I used C, I would get this:

i1 : 0x9f4f99fb2c
i2 : 0x9f4f99fb28
i3 : 0x9f4f99fb24

推荐答案

将堆栈视为功能堆栈帧序列,而不是可变地址序列.不管堆栈增长的方向如何,它都会以整个堆栈帧的增量增长,每个帧的大小都不同.

Think of the stack as a sequence of function stack frames, not a sequence of variable addresses. Regardless of the direction that the stack grows, it grows in increments of whole stack frames, which are different sizes for each function.

函数的堆栈框架的布局具有绑定变量的固定位置,类似于结构,但是不能保证框架内绑定的确切顺序.如果可以使该功能在不同的布局下更有效地利用空间,那么它可能会这样做.例如:

The layout of a function's stack frame has fixed positions for where variables will be bound, similar to a struct, but the exact order of bindings within the frame is not guaranteed. If the function can be made to use space more efficiently with a different layout, it probably will. For example:

fn main() {
    let i1: i32 = 1;
    let i2: i64 = 2;
    let i3: i32 = 3;
    println!("i1 : {:?}", &i1 as *const i32);
    println!("i2 : {:?}", &i2 as *const i64);
    println!("i3 : {:?}", &i3 as *const i32);
}

// i1 : 0x7fff4b9271fc
// i2 : 0x7fff4b927200
// i3 : 0x7fff4b92720c

在这里,i3存储在之前 i2. i64需要与64位的倍数对齐,因此将两个i32存储在一起而不是留有空隙会更紧凑.在调试版本中不会发生这种情况,并且编译器可以也可以选择先存储具有相同效果的i3,因此我们不能也不应该依赖此顺序.

Here, i3 is stored before i2. An i64 needs to be aligned to a multiple of 64 bits so it is more compact to store the two i32s together rather than leaving a gap. This doesn't happen in debug builds, and the compiler could also have chosen to store i3 first with the same effect, so we cannot and should not rely on this ordering.

也有可能出于任何其他优化原因(例如缓存访问效率)对变量进行重新排序.

It's also possible that variables could be reordered for any other optimisation reasons, such as cache access efficiency.

要查看堆栈实际上是否向下增长,请考虑具有多个功能的示例:

To see that the stack does actually grow downwards, consider an example with multiple functions:

fn main() {
    let i1 = 1;
    println!("i1 : {:?}", &i1 as *const i32);

    another();
}

#[inline(never)]
fn another() {
    let i2 = 2;
    println!("i2 : {:?}", &i2 as *const i32);
}

// i1 : 0x7fffc7601fbc
// i2 : 0x7fffc7601f5c

anothermain调用,因此其堆栈帧的地址较低.注意,我不得不强制编译器不要内联函数,否则组合的布局将是任意的.

another is called by main so its stack frame has a lower address. Notice that I had to force the compiler not to inline the function, otherwise the combined layout would have been arbitrary.

这篇关于为什么后续的Rust变量增加堆栈指针而不是减少堆栈指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆