指向释放的变量更改地址的指针

时间:2019-07-31 08:53:34

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

此代码:

#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

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

repro case

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

很抱歉没有提及我的IDE。

2 个答案:

答案 0 :(得分:3)

访问fun的返回值具有实现定义的行为,因为它返回了无效的指针值(请参见下面的引用,原因)。在特定平台上,它甚至可能生成运行时错误。因此,p的值也是实现定义的。很有可能,它将成为无效的指针值,因此访问它是实现定义的。

basic.std/4

  

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

答案 1 :(得分:2)

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