【问题标题】:Memory: how does the compiler choose where to store variables? [duplicate]内存:编译器如何选择存储变量的位置? [复制]
【发布时间】:2014-12-09 23:15:34
【问题描述】:

给定两个函数,func1 和 f2,具有以下签名:

void func1(){
    int baba = 12345;
    // printf the value of baba here
}

void f2(){
    int loo;
    //printf the value of loo here
}

...如果我运行我的 int main,它只有 func1 然后是 f2:

int main(){
      func1();
      f2();
}

...那么 baba 和 loo 的打印值都是 12345。所以我的问题如下:

  1. 这是已定义的行为,还是只是我的机器出现的错误?

  2. 如果这不是我的计算机所做的错误,您能解释一下为什么编译器选择将loo 存储在与baba? 相同的地址中

编辑:我想我应该问一下,如果我有这两个确切的功能,那么 baba 和 loo 在任何机器上都会有相同的值吗?

我了解 loo 的价值是 baba 剩余位的结果,并且我了解(至少在我的机器上)两者的堆栈都被布置为使 loo 重叠到 baba 的旧领土上。 真的每台机器都会以 baba 和 loo 重叠的方式放置这两个函数堆栈吗?完全按照写的方式使用这两个函数,也就是……

【问题讨论】:

  • 想一想临时局部变量如何在堆栈上分配,然后应该是显而易见的。
  • 1.它的UB。 2.它是代码中的错误,而不是编译器。 loo 不确定。评估它会调用 UB。为什么使用相同的地址选择取决于实现。
  • 如果在调用func1()f2() 之间发生中断,则(堆栈指针下方)堆栈上的前一个12345 将无法生存。
  • 我认为这是未定义的行为。它的工作方式是,当您调用 func1 时,堆栈被压入,并将值 12345 分配给新堆栈帧中的地址。当您离开 func1 时,堆栈将弹出回调用堆栈帧。当您调用 f2 时,堆栈再次被压入,并且由于两次调用中的参数数量相同(无),因此 loo 内存中的位置现在是 baba 所在的位置,这部分内存尚未被擦除并包含相同的数据。
  • 我很困惑为什么这个问题被标记为已回答并链接到另一个问题。如果已经回答,应该是类似的问题。

标签: c++ c memory compiler-construction runtime


【解决方案1】:

f2() 中,lolo 未初始化。因此它的内容是undefined

然而,大多数情况下,内容似乎是堆栈上的数据。巧合的是,您首先调用了func1(),它的内存/堆栈布局与f2() 完全相同。因此,该变量偶然包含先前存储在同一位置的数据。

这种行为根本无法保证。它似乎只在这个特定的上下文中工作,因为在两次调用之间没有创建其他局部变量,并且没有其他函数调用用其他内容覆盖数据(并且两个函数具有完全相同的内存布局)。

这里用一张小图来说明这个具体案例的情况:

【讨论】:

  • 我在“未定义行为”中使用“未定义”,即 C++ 标准没有定义行为。但未定义/不确定并不意味着它是随机的。所以我敢于维护:“它只在这个特定情况下在这个编译器上工作,在这个操作系统上具有相同的编译开关”
猜你喜欢
  • 2013-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
  • 2020-07-27
相关资源
最近更新 更多