堆栈上的局部变量分配顺序

堆栈上的局部变量分配顺序

看看这两个功能:

void function1() {
    int x;
    int y;
    int z;
    int *ret;}void function2() {
    char buffer1[4];
    char buffer2[4];
    char buffer3[4];
    int *ret;}

如果我打破function1()gdb,并打印变量的地址,我得到这个:

(gdb) p &x  
$1 = (int *) 0xbffff380(gdb) p &y
$2 = (int *) 0xbffff384(gdb) p &z
$3 = (int *) 0xbffff388(gdb) p &ret
$4 = (int **) 0xbffff38c

如果我做同样的事情function2(),我得到这个:

(gdb) p &buffer1
$1 = (char (*)[4]) 0xbffff388(gdb) p &buffer2
$2 = (char (*)[4]) 0xbffff384(gdb) p &buffer3
$3 = (char (*)[4]) 0xbffff380(gdb) p &ret
$4 = (int **) 0xbffff38c

您会注意到,在两个函数中,ret都存储在最靠近堆栈顶部的位置。在function1(),接下来是zy最后x。在function2()ret然后是buffer1,然后buffer2buffer3。为什么存储顺序发生了变化?我们在两种情况下使用相同数量的内存(4字节ints与4字节char数组),因此它不能成为填充问题。这种重新排序有什么原因,而且,通过查看C代码可以提前确定如何排序局部变量?

现在我知道C的ANSI规范没有说明存储局部变量的顺序,并且允许编译器选择自己的顺序,但我想编译器有关于它如何处理的规则这个,并解释为什么这些规则是这样的。

作为参考,我在Mac OS 10.5.7上使用GCC 4.0.1


互换的青春
浏览 501回答 3
3回答

慕运维8079593

我不知道为什么GCC按照它的方式组织它的堆栈(虽然我猜你可以破解它的源或本文并找出),但是我可以告诉你如何保证特定堆栈变量的顺序如果由于某种原因你需要。简单地将它们放在一个结构中:void function1() {     struct {         int x;         int y;         int z;         int *ret;     } locals;}如果我的记忆正确地为我服务,spec保证&ret > &z > &y > &x。我离开了我的K&R工作,所以我不能引用章节和诗句。

吃鸡游戏

所以,我做了一些实验,这就是我发现的。它似乎是基于每个变量是否是一个数组。鉴于此输入:void f5() {         int w;         int x[1];         int *ret;         int y;         int z[1];}我最终在gdb中得到了这个:(gdb) p &w $1 = (int *) 0xbffff4c4(gdb) p &x $2 = (int (*)[1]) 0xbffff4c0(gdb) p &ret  $3 = (int **) 0xbffff4c8(gdb) p &y $4 = (int *) 0xbffff4cc(gdb) p &z $5 = (int (*)[1]) 0xbffff4bc在这种情况下,ints和指针首先处理,最后在堆栈顶部声明,然后首先声明更接近底部。然后以相反的方向处理数组,声明越早,堆栈中的最高位。我确信这是有充分理由的。我不知道它是什么。

繁花如伊

ISO C不仅没有说明堆栈上局部变量的排序,它甚至不能保证堆栈甚至存在。该标准只讨论了块内变量的范围和生命周期。
打开App,查看更多内容
随时随地看视频慕课网APP