【问题标题】:Pointer to deallocated variable changes address指向已释放变量更改地址的指针
【发布时间】:2019-07-31 08:53:34
【问题描述】:

这段代码:

#include <iostream>

using namespace std;

int* fun()
{
    int a = 5;
    int* pointerA = &a;

    cout << pointerA << endl;

    return pointerA;
}

int main()
{

    int* p = fun();

    cout << p << endl;

    return 0;
}

打印以下内容:

0x[some address]
0

我知道当函数fun()返回时变量a被释放,但是为什么cout &lt;&lt; p &lt;&lt; endl;返回0?即使变量在技术上不再存在,它不应该仍然指向内存中的相同地址吗?这是编译器功能还是未定义的行为?

repro case

编辑:我找到了罪魁祸首。我正在使用 CodeBlocks,在这个项目的构建选项中,有一个标志“优化更多(速度)[-O2]”。如果选中它,我会得到0,如果我取消选中该标志,我会得到相同的地址0x[some address],这是预期的行为。

我很抱歉没有提到我的 IDE。

【问题讨论】:

  • 难道它不应该仍然指向内存中的同一个地址,即使变量在技术上已经不存在了吗? -- 当你编写类似的东西时,编译器的优化器会做出惊人的事情这个,同意吗?您知道它的代码可能不起作用,但同时您说“它应该起作用”。
  • 这意味着该代码的某处实际上是UB,否则不允许优化器优化它。
  • 返回指向局部变量的指针然后访问该指针是未定义的行为。指针的访问可能是多么良性并不重要——行为是未定义的。
  • @VTT from [basic.stc.dynamic.deallocation]:The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.“使用无效指针值”是否不包括 OP 的情况?
  • 不应该还是指向内存中的同一个地址 无意义的问题。无效的指针值不代表地址。

标签: c++ pointers language-lawyer undefined-behavior object-lifetime


【解决方案1】:

访问fun 的返回值具有实现定义的行为,因为它返回一个无效的指针值(参见下面的引用,为什么)。在特定平台上,它甚至可能产生运行时错误。所以,p 的值也是实现定义的。很可能,它会变成无效的指针值,所以访问它是实现定义的。

basic.std/4:

当一个存储区域的持续时间结束时,表示该存储区域任何部分地址的所有指针的值都变为无效指针值。通过无效指针值的间接传递以及将无效指针值传递给释放函数具有未定义的行为。 对无效指针值的任何其他使用都具有实现定义的行为

【讨论】:

  • std 的哪一部分需要 impl 来记录行为?
【解决方案2】:

这可能是一个编译器特性。在这种情况下,很容易看出 fun 返回的指针是无效的,因此进一步使用该指针将导致未定义的行为。如果您尝试不同的编译器,它可能会有所不同。例如。对我来说,在 Visual Studio 2012 中它确实返回实际地址而不是 0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2014-09-05
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    相关资源
    最近更新 更多