3

我研究过在linux系统中堆栈从高内存地址增长到低内存地址。为了测试这一点,我写了一个小代码:

#include<stdio.h>
void func() {
    int var1;
    int var2;
    printf("Func: %p %p",&var1,&var2);
}
 
int main() {
    int var1;
    int var2;
    printf("Main: %p %p\n",&var1,&var2);
    func();
    return 0;
}

当我在 ideone 中运行它时,我得到以下输出:

Main: 0xbfd958f0 0xbfd958f4
Func: 0xbfd958f8 0xbfd958fc

根据教科书,Func 应该存储在比 Main 更低的内存地址中,但这里发生的情况完全相反。有人可以向我解释这种行为。这是ideone 的链接

谢谢你。

4

1 回答 1

-3

通常堆栈从高内存向下增长,而堆从低内存增长,因此它们永远不会“碰撞”彼此。

不过,理论上堆栈可以朝任一方向增长。x86 支持向任一方向增长的堆栈,但我从未见过有人故意使用向上增长的堆栈。

最好的部分是英特尔将向下增长的堆栈称为“增长”,将向上增长的堆栈称为“向下增长”。

注意:-您不应该假设堆栈框架内的局部变量的顺序。编译器可能会将“first”变量“first”放在将其推送到当前位置的意义上,这意味着“first”变量位于更高的地址。或者它可以在内存中向上组织变量(更有可能)给“第一个”变量一个较低的地址。或者它可以完全随机排列变量。如果进行优化,它甚至可以消除变量,或者如果变量的生命周期不重叠,则将同一内存位置用于多个变量。

您可以点击此链接 BUFFER OVERFLOW 7

但仍然重要的是要知道返回地址不能保证以任何特定方式排列。如果-fomit-frame-pointer使用,则基指针将不在堆栈上。正如我之前所说,局部变量的顺序不符合特定约定。

另一个复杂情况是在同一个程序中存在多个调用约定。仅仅通过查看代码地址来判断函数遵循什么约定通常是不可能的。堆栈帧可能看起来与您所期望的非常不同。

于 2014-07-28T08:09:31.700 回答