请考虑这个简单的例子:
#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
的第一次读取会导致有效的记忆,但第二次连续即时读取会导致垃圾。同样在本地的任何呼叫地址都是一样的。我一直认为堆栈变量的内存是在每次函数调用时分配的,并在返回后释放,但我不能从这个角度解释程序的输出。
答案 0 :(得分:2)
&#34;释放&#34;自动存储不会使存储器消失,或改变存储在那里的位模式。它只是使它可以重用,如果你试图访问曾经存在的对象,它会导致未定义的行为。
从函数返回后,本地占用的内存可能没有被覆盖,因此读取它可能会给出函数内分配的值。
在调用另一个函数(在本例中为operator<<()
)之后,内存可能已经被重用于该函数中的变量,因此可能具有不同的值。
答案 1 :(得分:1)
你是对的,undefined behaviour。
除此之外,发生的是std::cout << *hackPointer
涉及函数调用:operator<<()
在读取*hackPointer
的值后被调用。很有可能,operator<<()
使用自己的局部变量,这些变量最终位于local
所在的堆栈上,消灭后者。