c ++读取前一个函数堆栈帧

时间:2015-12-23 02:37:40

标签: c++ arrays stack

我有一个由函数创建的数组(名为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。

据我所知,当一个函数返回时,它不会清理它的堆栈帧。因此,当读取读取堆栈时,它会读取写入写入的相同值。 但为什么第一和第二个值总是这样?

2 个答案:

答案 0 :(得分:2)

正如其他人所指出的,这种行为是完全未定义的,因此即使您运行此代码1000次并看到此行为,您可能会看到第1001次不同的内容。此外,您所看到的以及为什么将依赖于实现。如果您对更好地理解这一点感到非常好奇,我建议您查看编译器生成的汇编代码,以便更好地了解堆栈的内容。你如何做到这一点再次依赖于实现,但是使用gcc你可以将--save-temps选项传递给编译器,它会吐出它的中间文件供你仔细阅读。这可能非常有教育意义!

答案 1 :(得分:1)

阵列在堆栈空间中占据相同的一般附近,但这只是一个巧合。如果read()或write()中有更多变量,则不再是这种情况。堆栈框架的结构是编译器中的实现细节 - 它取决于许多因素,例如函数中的变量,优化级别,编译器可能在堆栈上分配的临时存储空间,展开函数异常的数据或它的被告可能会抛出...简而言之,不要依赖它。

从C ++标准的角度来看,读取未初始化的变量(如array中的read)是一种未定义的行为 - 任何事情都可能发生,从伪造值到程序崩溃。< / p>