我有一个由函数创建的数组(名为write)。在该函数返回后,我调用另一个函数(名为read),它直接从栈中读取相同大小的数组。
#include <iostream>
using std::cout;
using std::endl;
void write();
void read();
int main(void)
{
write();
read();
return 0;
}
// Write an array of 10 ints to the stack
void write() {
int array[10];
for(int i = 0; i < 10; i++)
array[i] = i;
}
// Read an array of 10 from stack
void read() {
int array[10];
for(int i = 0; i < 10; i++)
cout << array[i] << endl;
}
读取函数不应该从堆栈中读取相同的数组内容吗?
我感到有趣的是第一个和第二个数组值始终相同。第一个(在索引0处)是负垃圾值。第二个(在索引1处)为0。
据我所知,当一个函数返回时,它不会清理它的堆栈帧。因此,当读取读取堆栈时,它会读取写入写入的相同值。 但为什么第一和第二个值总是这样?
答案 0 :(得分:2)
正如其他人所指出的,这种行为是完全未定义的,因此即使您运行此代码1000次并看到此行为,您可能会看到第1001次不同的内容。此外,您所看到的以及为什么将依赖于实现。如果您对更好地理解这一点感到非常好奇,我建议您查看编译器生成的汇编代码,以便更好地了解堆栈的内容。你如何做到这一点再次依赖于实现,但是使用gcc你可以将--save-temps
选项传递给编译器,它会吐出它的中间文件供你仔细阅读。这可能非常有教育意义!
答案 1 :(得分:1)
阵列在堆栈空间中占据相同的一般附近,但这只是一个巧合。如果read()或write()中有更多变量,则不再是这种情况。堆栈框架的结构是编译器中的实现细节 - 它取决于许多因素,例如函数中的变量,优化级别,编译器可能在堆栈上分配的临时存储空间,展开函数异常的数据或它的被告可能会抛出...简而言之,不要依赖它。
从C ++标准的角度来看,读取未初始化的变量(如array
中的read
)是一种未定义的行为 - 任何事情都可能发生,从伪造值到程序崩溃。< / p>