【问题标题】:Why does this stack variable not get overwritten although it is out of scope?为什么这个堆栈变量没有被覆盖,尽管它超出了范围?
【发布时间】:2020-07-04 08:43:42
【问题描述】:

AFAIK,在堆栈上声明的变量只存在于当前范围结束之前,所以基本上直到下一个 } 出现。但是,让我们举个例子:

int main() {
    int* ptrOne;
    {
        int intOne = 1;
        ptrOne = &intOne;
    }
    int intTwo = 9;

    std::cout << *ptrOne;
}

intTwo 被声明时,intOne 已经超出范围。它不再可访问,因此应该被覆盖。但是,cout 仍然有效并输出1。在内存视图中,我可以看到 1 仍然存在,而 9 在其后面写入了几个字节。为什么? (我正在使用带有 MSVC 的 Visual Studio 2019)

【问题讨论】:

  • 这是未定义的行为。谁知道会发生什么?
  • 因此应该被覆盖。 -- 你从哪里得到这样的想法?永远不要假设编译器做了什么,除非自己编写了代码并且知道做了什么,或者它记录了(在 C++ 标准中,由编译器供应商等)做了什么。

标签: c++ pointers stack


【解决方案1】:

它不再可访问,因此应该被覆盖。

不正确,正确的说法是it is no longer accessible and so the program has undefined behaviour。您无法对具有未定义行为的程序进行推理,它们可以为所欲为。

【讨论】:

  • 但是栈上的变量什么时候被删除呢?这些不可访问的是否会永远挂起,直到堆栈溢出?
  • @CheeseCrustery 在有效程序中堆栈变量被删除,在无效程序中任何事情都可能发生。
  • 如果你有一个有效的程序,它必须遵循 C++ 的规则,这意味着堆栈变量被销毁(不是删除,那是别的东西)。但无效的 C++ 程序不必遵守规则。他们可以做任何事情,这就是未定义行为的含义。
  • 在这种情况下,intOne 之前占用的存储空间还有什么用途? intTwo 从未使用过,因此没有理由将其存储到内存中,即使它可能完全存在于寄存器中,除非你给编译器一个理由,它确实需要存储到内存中。
  • @CheeseCrustery -- 不能保证这些变量在堆栈中。它们可以被优化并放置在寄存器中。
猜你喜欢
  • 2021-05-20
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
  • 2022-08-10
  • 2013-05-24
相关资源
最近更新 更多