调用堆栈在 2 个函数调用之间重用

标签 c

下面的简单 C 程序输出 42 令我惊讶。我预计它会输出垃圾值或 0,因为堆栈帧对于 foo()bar() 是不同的。输出如何确定为 42

#include <stdio.h>
void foo(void){
    int a;
    printf("%d\n",a);
}

void bar(){
    int a=42;
}

int main(){
    bar();
    foo();
    return 0;
}

>>gcc -o test test.c

>>./test

42

当我指示编译器优化代码时,它打印出垃圾!

>>gcc -O -o test test.c

>>./test

2487239847

最佳答案

是的,值 42 是垃圾。这是对它的解释:

堆栈中的每个函数,都以类似的顺序开始

  1. 函数的参数
  2. 函数的返回值
  3. EBP(存储前一帧指针)
  4. 异常处理框架
  5. 局部变量
  6. 缓冲区
  7. 被叫保存寄存器

在上面的例子中,main() 被调用并遵循上面的过程。

然后遇到bar()按照1,2,3,4步骤将局部变量a=42存入内存(5)然后后面跟着6,7那么它就会从内存中出来。

然后它遇到 foo() 遵循与 bar() 具有的内存位置相同的 1、2、3、4 步。并且您声明了一个名为 a 的局部变量,它将指向与保存局部变量 a=42bar() 相同的内存位置。所以它在打印时给出了相同的值 42,这实际上是一个垃圾值。

要验证这一点,试试这个例子:这会打印 7

#include <stdio.h>
#include <string.h>

void foo() {
    int b;
    printf("%d\n",b);
}

void zoo() {
  int dummy = 7;
}
void bar(){
    int a1=3;
}

int main(){
    bar();
    zoo();
    foo();
    return 0;
}

引用:Doc

关于调用堆栈在 2 个函数调用之间重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42498427/

相关文章:

c - ARM 汇编中的段错误

c - 您如何使输入接受 3 个参数

c - 为什么 ffdec_h264 在 gstreamer 中不给出调试信息?

c - 为什么使用 lz4 lib 解压数据失败,但使用 unlz4 却可以正常工作?

c - strtof 未定义;假设 extern 返回 int

c - 使用与其他文件相同的名称命名文件

C++:在 C 或 C++ 中以普通文本模式(非二进制)写入 vector 文件以输出最快

c - 文本文件编辑 C

c - 如何实现 timespec 累加器?

c - .bin 和 .dat 文件有什么区别?