Rust中的堆栈指针会递增吗?

时间:2019-01-28 04:29:20

标签: pointers memory rust stack allocation

当然没有什么太严重的,但是我发现在Rust中创建静态分配的变量时,似乎随着堆栈指针的增加而感到奇怪(我不知道这种情况,因为随着内存分配,堆栈指针减少了)。如果我要在C中做同样的事情,显然随着我创建更多变量,堆栈指针会减少。知道为什么会这样吗?可能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);
}

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

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

例如,如果我使用C,则会得到以下信息:

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

1 个答案:

答案 0 :(得分:2)

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

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

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

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


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

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调用,因此其堆栈帧的地址较低。请注意,我不得不强迫编译器不要内联函数,否则组合的布局将是任意的。