C Linux中堆栈的错误增长方向

C Linux中堆栈的错误增长方向,c,linux,memory-layout,C,Linux,Memory Layout,我曾经研究过,在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\

我曾经研究过,在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;
}
根据教科书,Func应该存储在比Main更低的内存地址中,但这里发生的事情完全相反。谁能给我解释一下这种行为。这是你的电话号码


谢谢。

通常,堆栈从高内存向下扩展,而堆从低内存向上扩展,因此它们不会相互“碰撞”

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

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

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

你可以点击这个链接

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


另一个复杂问题是在同一个程序中存在多个调用约定。通常,仅仅通过查看代码地址来判断函数符合何种约定是不可能的。堆栈帧可能与您期望的非常不同。

编译器可以随意重新排序堆栈变量。@Mysticial::我知道这是真的,但您仍然可以为此引用一个很好的链接。编译器可以使用的纬度确实会影响您的输出。例如,我的macbook air使用clang 3.4会产生以下输出差异,这可能与您的预期完全不同。正如WhozCraig所说,这可能是优化的结果,可能编译器实际上没有将func()作为函数调用。如果func()是一个函数调用,那么编译器无法更改堆栈布局,该布局是在ABI中指定的。它确实会抛出调用,我可以将其归因于优化器。调试asm提供,而发布asm提供。后者不调用
func()
,而是选择完全内联。奇怪的是,与中的讨论类似。x86上的堆栈不会向上增长。你从哪里得到这些信息的?@Jongware:你说得对,先生!!。。。它来自同一个地方…但没有人能知道每件事,对吗??我试图弄明白,我发现这篇文章很有启发性。。。。如果你认为这是错误的,这对我来说是可以接受的…请分享你的研究,这样我也可以学习。。。谢谢
Main: 0xbfd958f0 0xbfd958f4
Func: 0xbfd958f8 0xbfd958fc