【问题标题】:Stack execution in C [duplicate]C中的堆栈执行
【发布时间】:2019-04-15 17:29:49
【问题描述】:

如下代码

#include <stdio.h>

void f() {
  int x;
  printf("x = %d\n", x);
}

void g() {
  int y = 42;
  printf("y = %d\n", y);
}

int main() {
  f();
  g();
  return 0;
}

我得到以下输出

x = 22031
y = 42

如果我更改main() 中执行的最后两个函数的顺序并运行代码

void f() {
  int x;
  printf("x = %d\n", x);
}

void g() {
  int y = 42;
  printf("y = %d\n", y);
}

int main() {
  g();
  f();
  return 0;
}

我得到以下信息:

y = 42
x = 42

谁能给我解释一下。我知道这与内存在地址中的分配方式有关,但我不确定细节。

【问题讨论】:

标签: c memory stack


【解决方案1】:

您在内存中看到来自“其他”的未初始化值,即undefined behavior。当您运行程序时,您会在内存中获取并看到“旧”值,这些值来自计算机中的程序以外的其他东西。

例如,以下程序将遇到未定义的行为,因为x 在初始化之前已被读取,并且 x 的值来自另一个进程:

#include <stdio.h>

int main() {
    int x;
    printf("x = %d\n", x);
    return 0;
}

【讨论】:

  • 我不会说它是大多数现代操作系统上的“来自其他进程的旧值”。能够随机读取其他程序中的内容将是一场安全噩梦。
  • @Groo 我把它改成了“你的程序以外的东西”......我的意思是我认为这个值可能是你上次运行程序时的剩余值。跨度>
【解决方案2】:
x = 22031
y = 42

X 值是未初始化的堆栈垃圾值。当您的程序加载到 RAM 中时,它不会将堆栈或堆内存归零。这是C programs memory model 的参考。

有趣的情况是当

y = 42
x = 42

那么这里发生了什么?好吧,当您首先调用 g 函数时,您会将值弹出到堆栈中(在内存模型中向下增长,或者如果内存模型不同,则向上)。下次您调用 f 函数时,未初始化的堆栈垃圾的值已更改为您调用 g 时分配的值(将 y 的地址分配给 42)。这是因为您在两个函数中将相同数量的参数和局部变量推入堆栈,如果您调整它们,您将看到不同的值。例如,下面的 g 定义可能会导致 x 打印 43,这取决于局部变量如何弹出到堆栈中。

void g() {
  volatile int z = 43;
  int y = 42;
  printf("y = %d\n", y);
}

如果你想弄乱这个,让编译器不会优化它“z”。

【讨论】:

  • 标准没有像您链接到的那样指定堆栈或堆或内存模型;这些都是并不总是适用的实现细节。
  • @DavidBowling 虽然我不同意你所说的,但你能链接我一个堆栈内存模型,它在 y=42, x=42 的情况下会有所不同吗?我认为相同数量的内存被弹出,然后关闭,然后以相同的方式“一致地”产生 x=42 (使用这个 OP 示例)。对于单个线程,我不知道在这些情况下会执行不同的另一种堆栈内存模型,尽管标准中可能没有概述以这种方式运行。需要明确的是,堆栈是向上还是向下增长以使 x=42 可重现并不重要。
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 2020-04-19
  • 1970-01-01
  • 2016-05-09
  • 2010-10-14
  • 2018-02-22
  • 1970-01-01
  • 2012-01-28
相关资源
最近更新 更多