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

c++ reading previous function stack frame

本文关键字:堆栈 函数 上一个 读取 c++      更新时间:2023-10-16

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

read函数不应该从堆栈中读取相同的数组内容吗?

我发现有趣的是,第一个和第二个数组值总是相同的。第一个(在索引0处)是一个负垃圾值。第二个(位于索引1处)为0。

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

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

数组在堆栈空间中占据相同的一般邻域,但这只是巧合。如果read()或write()中有更多的变量,那么情况就不再是这样了。堆栈框架的结构是编译器中的一个实现细节-它取决于许多事情,如函数中的变量、优化级别、编译器可能在堆栈上分配的临时存储空间、为函数或其被调用者可能抛出的异常展开数据。。。简而言之,永远不要依赖它。

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