【问题标题】:gcc: access to destroyed stack variable by using reference possible? [duplicate]gcc:可以使用引用访问被破坏的堆栈变量吗? [复制]
【发布时间】:2012-05-04 20:29:41
【问题描述】:

可能重复:
Can a local variable's memory be accessed outside its scope?

考虑以下简单的 C++ 代码:

#include <iostream>

struct Test
{
    Test( int i )
        :   ref( i ),
            ptr( &i ) {}

    int &ref;
    int *ptr;
};

int main()
{
    Test t( 5 );

    std::cout << t.ref << std::endl;
    std::cout << *t.ptr << std::endl;

    return 0;
}

Test 类存储了一个指针和一个指向栈中局部变量 i 的引用。我会假设我在从 Test 构造函数返回后被破坏了。但显然情况并非如此。因为这是程序的输出:

5
134513968

访问指针的结果是我所期望的:每次运行都会改变的随机值。但是引用访问总是导致 5 - 只要局部变量 i 仍然存在。

谁能向我解释这种行为?我在 64 位 Linux(4.6.3 版)上使用 g++。

问候, enuhtac

【问题讨论】:

  • 感谢您的回答。我只是想知道我是否错过了 C++ 标准中的一些非常特殊的话题。显然,情况并非如此。这个小程序给出了正确的答案纯属偶然

标签: c++ pointers gcc reference dereference


【解决方案1】:

像这样访问被破坏的变量会导致undefined behaviour。打印 5 只是巧合;它可能会打印 -4390843 或 hello world,让你的电脑崩溃,点燃气氛,或者用你的信用卡买披萨。

此外,试图猜测发生了什么真的没有意义,因为编译器在生成程序集时可以对您的代码做一些非常奇怪的事情。这是一个徒劳的练习(但如果你真的想知道所有的位从哪里来以及它们去过哪里,只需调试它)。

【讨论】:

  • 我在哪里可以获得类似的崩溃行为@@@@@@ - SEGFAULT Pizza on the way
  • @lukecampbell 简单:signal(SIGSEGV, Dominos);
  • @JoeFish 我想我这个周末刚刚找到了一个新项目,只需要了解 Dominos.com 是否有 RESTful API(怀疑)
【解决方案2】:

在构造t 时,您将获得i 在构造期间存储的内存地址。当您调用 std::cout &lt;&lt; t.ref 时,没有理由将该内存位置用于其他用途,因此该值仍然存在。

但是,没有什么是你可以信任的。在i 超出范围后访问该内存位置是未定义的行为。

【讨论】:

    【解决方案3】:

    我没有仔细检查它,但仅仅因为您从堆栈中弹出并不意味着内容被覆盖或更改,该地址中的值保持不变。之后再添加一些方法调用,它应该会改变。

    【讨论】:

      【解决方案4】:

      不保证会立即删除局部变量。它可以保留在内存中。但这是未定义的行为,而且很危险。

      【讨论】:

        【解决方案5】:

        This answer 提供了一个很好的类比来说明您如何思考这个问题:

        您租了一间酒店房间。你把一本书放在床头柜最上面的抽屉里 表,去睡觉。您第二天早上退房,但“忘记”了 交还你的钥匙。你偷了钥匙!

        一周后,你回到酒店,不办理入住,潜入 你的旧房间和你偷来的钥匙,然后看看抽屉。你的书 还在那里。太棒了!

        怎么可能?不是酒店房间抽屉里的东西吗 如果您没有租用房间,则无法访问?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-01-06
          • 2013-05-20
          • 2018-11-02
          • 1970-01-01
          • 1970-01-01
          • 2020-09-02
          • 2016-04-02
          相关资源
          最近更新 更多