简体   繁体   English

为什么后续的Rust变量增加堆栈指针而不是减少堆栈指针?

[英]Why do subsequent Rust variables increment the stack pointer instead of decrementing it?

I find it odd how when you create statically-allocated variables in Rust that it seems as the stack pointer increases. 我觉得奇怪的是,当您在Rust中创建静态分配的变量时,似乎随着堆栈指针的增加而增加。 I know this is not the case since the stack pointer decreases as memory is allocated. 我知道不是这种情况,因为堆栈指针随着分配的内存而减少。

If I were to do the same thing in C, I would see the stack pointer decrease as I created more variables. 如果要在C中做同样的事情,我会发现随着创建更多变量,堆栈指针会减少。

Why is it this way? 为什么这样呢? Does the Rust compiler allocate these from bottom to top instead on top to bottom? Rust编译器是否从下至上而不是从上至下分配这些?

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

If I used C, I would get this: 如果我使用C,我将得到:

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

Here, i3 is stored before i2 . 在此, i3 i2 之前存储。 An i64 needs to be aligned to a multiple of 64 bits so it is more compact to store the two i32 s together rather than leaving a gap. i64需要与64位的倍数对齐,因此将两个i32存储在一起而不是i32是更紧凑的。 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. 这不会发生在调试版本中,编译器也可以选择存储i3先用同样的效果,所以我们不能和不应该依赖于这种排序。

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

another is called by main so its stack frame has a lower address. anothermain调用,因此其堆栈帧具有较低的地址。 Notice that I had to force the compiler not to inline the function, otherwise the combined layout would have been arbitrary. 注意,我不得不强制编译器不要内联函数,否则组合的布局将是任意的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM