堆栈变量生命周期好奇的例子

时间:2014-12-23 11:46:23

标签: c++

请考虑这个简单的例子:

#include <iostream>

const int CALLS_N = 3;
int * hackPointer;

void test()
{
    static int callCounter = 0;
    int local = callCounter++;
    hackPointer = &local;
}

int main()
{
    for(int i = 0; i < CALLS_N; i++)
    {
        test();

        std::cout << *hackPointer << "(" << hackPointer << ")";
        std::cout << *hackPointer << "(" << hackPointer << ")";

        std::cout << std::endl;
   }
}

输出(VS2010,没有优化的MinGW)具有相同的结构:

0(X) Y(X)
1(X) Y(X)
2(X) Y(X)
...
[CALLS_N](X) Y(X)

其中X - 内存中的一些地址,Y - 一些垃圾编号。
这里做的是未定义行为的情况。但是我想了解为什么在当前条件下存在这样的行为(对于两个编译器来说它是相当稳定的) 似乎在test()调用后,hackPointer的第一次读取会导致有效的记忆,但第二次连续即时读取会导致垃圾。同样在本地的任何呼叫地址都是一样的。我一直认为堆栈变量的内存是在每次函数调用时分配的,并在返回后释放,但我不能从这个角度解释程序的输出。

2 个答案:

答案 0 :(得分:2)

&#34;释放&#34;自动存储不会使存储器消失,或改变存储在那里的位模式。它只是使它可以重用,如果你试图访问曾经存在的对象,它会导致未定义的行为。

从函数返回后,本地占用的内存可能没有被覆盖,因此读取它可能会给出函数内分配的值。

在调用另一个函数(在本例中为operator<<())之后,内存可能已经被重用于该函数中的变量,因此可能具有不同的值。

答案 1 :(得分:1)

你是对的,undefined behaviour

除此之外,发生的是std::cout << *hackPointer涉及函数调用:operator<<()在读取*hackPointer的值后被调用。很有可能,operator<<()使用自己的局部变量,这些变量最终位于local所在的堆栈上,消灭后者。