如何在C ++中使用堆栈

时间:2016-11-12 20:01:17

标签: c++ c memory memory-management

我尝试在执行C ++程序时理解内存管理。我知道在调用函数时,函数框架放在堆栈上。它由该函数的所有局部变量组成。我也知道堆栈是一种数据结构,其组织方式只能访问顶部的数据。那么为什么在该函数内的所有行都可以访问任何局部变量?让我们考虑这个例子:

void function(int a, int b){ //Stack frame of function is placed on stack
a++; //variable a can be incremented
b++; //variable b can be incremented
a++; //variable a can be incremented again
}

因此,假设堆栈在代码的第一行之后以这种方式组织:

Variable a 
----------
Variable b
----------
(...)

所以我假设我可以在函数的第二行访问变量,因为它位于堆栈的顶部,但是我如何才能访问变量b呢? 我认为它就像变量a被拉出堆栈所以可以达到变量b。但为什么我可以在代码的下一行中找到变量a?它在上一步中被拉出了堆栈。

3 个答案:

答案 0 :(得分:3)

您将以上示例混合了粒度级别。

程序的调用堆栈不存储变量,它存储调用帧。变量是调用帧内的子对象(构成其中的大部分数据)。您认为只有顶部的数据才可以访问"是正确的,但堆栈顶部的单个对象是整个帧,而不是最新的变量,它包含当前调用的所有变量作为其子字段。由于一个对象是完整可见的,所有这些字段也是如此,因此所有当前调用的局部变量都是如此。

声明"只有顶部的数据才可访问"保持,因为在调用函数时,调用框架是不可见的,也不是它的任何变量。同样,所有这些变量只是一个对象的子字段,即前一帧。弹出当前帧时,所有这些帧同时再次可见,因为单个顶部对象整体可见。

这些都与内存管理无关。 "堆栈",用于指代内存,意味着完全超出C ++语言范围的东西,但嵌套函数调用形成的工作方式,如 a&#34纯的#34;堆栈,无论实现如何提供内存。

答案 1 :(得分:3)

定义C和C ++的标准不定义“堆栈”或“堆”。编译为物理硬件程序的实现通常将堆栈用于激活帧和局部变量,并使用堆进行动态分配。但是,相关标准根本不需要(因此也不能保证)。

有了这个,你的问题没有提到你感兴趣的平台。因此,我们不知道它的能力,所以讨论变量不是直接在上面的变量有点无意义。访问堆栈。

但是,我们可以考虑一下C for x86的流行实现如何处理这个例子:在函数的开头(函数的“序言”),帧大小只是添加到从堆栈指针中减去,之后通过相对于帧的间接寻址(堆栈指针或基本指针)访问局部变量。在函数结束时(函数的“结尾”),堆栈指针被恢复为指向返回地址。通常,现代x86编译器不会pushpop来“分配”或访问局部变量。

答案 2 :(得分:1)

要查看堆栈的使用方式,请编译代码以进行汇编。您可以使用g++ -S main.c使用g ++执行此操作。

然后,您可以看到堆栈正在做什么。

例如,pushq %rbp移动堆栈指针的位置,movl $1, -12(%rbp)将一个值(在本例中为值1)移动到堆栈顶部后面12个字节的内存位置,{ {1}}将堆栈后面的4个字节的值移动到movl -4(%rbp), %eax寄存器中。