堆栈内存是如何工作的,或者函数变量是如何在堆栈上分配和访问的
How does Stack memory work Or How are function variables allocated and accessed on the stack
例如,当我在本页上读到有关堆栈和堆的内容时,
我有一个问题,如果像页面上给出的例子一样,一个函数将其所有的局部变量都放在堆栈上,那么堆栈真的会访问不同的变量吗
因为堆栈通常只能访问顶部,所以它只能访问函数的一个变量
这是否意味着函数的变量存储在堆栈上的结构中?
堆栈指针,顾名思义,是一个与其他指针一样的指针,它指向正常的标准内存。要访问堆栈的任何区域,只需在指针上添加偏移即可。
如果你从C指针的角度来考虑它,你就得到了堆栈指针
char *stack_pointer = some_memory;
然后,该指针可以用作普通指针,包括添加偏移量以访问堆栈上的特定位置,例如
*(int *)(stack_pointer + 4) = 5;
我建议你试着学习汇编代码,然后你可以用一些局部变量制作一个非常简单的程序,并将其编译成汇编代码,阅读它,看看它是如何工作的。
stack semantics
和stack region
(或存储区域)之间经常存在混淆。相同的去堆。同样,"JVM和CLR等基于堆栈的虚拟机"的激增误导了非C和C++程序员,使他们认为本机运行时堆栈的工作方式也是一样的。
区分很重要
- 语义与区域——一个并不意味着另一个。C和C++堆栈不是Java/CLR堆栈
- "基于堆栈的调用帧",而不仅仅是"调用帧"-调用帧不必堆叠
大多数体系结构上的堆栈提供了O(1)
的随机访问语义。普通例如x86中的立即数和基址+偏移寻址模式以及堆栈和基址指针。实际堆栈区域是以后进先出法的方式分配的,但各个变量random accessible, O(1)
。如果你想让堆栈变得巨大,它可能是。
空间的分配就像后进先出法堆栈。变量可以像数组/向量一样在堆栈中访问,也可以通过绝对地址(指针)访问。
所以,不,在C和C++中,一次不局限于一个变量。
您对数据组织和访问有点困惑。堆栈内存的组织方式是,只能从"顶部"添加或删除新数据。然而,这与访问其他元素的限制无关。这样的限制可能存在于一些逻辑堆栈实现中(如C++STL中的std::stack
),但它们不是强制性的。
硬件堆栈实际上更像是一个固定大小的数组,具有可变的数组起始位置(堆栈指针),因此可以通过索引堆栈指针来访问其他元素。与"标准"数组的区别在于,它可以包含不同大小的元素。
堆栈框架由几个元素组成,包括:
-返回地址
程序中完成后返回功能的地址
-本地数据存储
为局部变量分配的内存
-参数存储
为功能参数分配的内存
-堆栈和基指针
运行时系统用于管理堆栈的指针
堆栈指针通常指向堆栈的顶部。堆栈基指针(帧指针)通常存在,并指向堆栈帧内的地址,例如返回地址。此指针有助于访问堆栈帧的元素。这两个指针都不是C指针。它们是运行时系统用来管理程序堆栈的地址。如果运行时系统是用C实现的,那么这些指针可以是真正的C指针。
您想知道的是堆栈帧是如何工作的。
要使用堆栈帧,必须有几个寄存器指向几个"堆栈";兴趣点";并修改它们或使用它们所指向的位置的偏移。例如:
CCD_ 6即将呼叫CCD_ 7。CCD_ 8的基由";基指针";注册EBP。到目前为止,main()
一直在为自己的堆栈帧使用所有寄存器。现在,如果要在调用后再次使用这些寄存器,则需要保存这些寄存器的内容。在调用之后,foo()
将(除其他外)通过为其局部变量分配内存来建立其自己的堆栈帧;堆栈指向";被称为ESP的寄存器移到其堆栈帧的顶部,同时保存CCD_;下一指令";注册名为EIP,这样它就知道在完成后返回到哪里。foo()
的堆栈帧现在位于main()
的堆栈帧之上,堆栈看起来像这样:
[保存了
foo()
的寄存器。]【
foo()
的局部变量】[
main()
基指针地址。EBP指向此处,并且在foo()
完成后将指向此处存储的地址。][
main()
返回地址(foo()
将返回到此地址所指向的位置)][
foo()
的参数。][保存了
main()
的寄存器。][…]
正如您所看到的,我们可以访问foo()
的自变量及其局部变量,作为EBP寄存器指向的简单偏移量。例如,如果第一个局部变量是4字节长,我们将在EBP-4中找到它。
- 堆栈变量超出范围时是否解除分配?
- 堆栈变量和函数C++奇怪的行为
- 野牛堆栈变量中的值分配
- 局部堆栈变量成员的返回值优化
- 访问其他线程堆栈变量如何在C++中工作?
- 指向堆栈变量的指针是否易失
- 是否可以 std::move 局部堆栈变量?
- 返回堆栈变量时停止调用析构函数
- 优化易失性堆栈变量的存储/构造是否合法
- SEGFAULT正在写入堆栈变量
- 汇编:C++堆栈变量地址不同/错误?
- C++11 Lambda闭包通过引用涉及一个堆栈变量,该变量离开作用域是允许的,但得到了未定义的行为
- 返回堆栈变量
- Visual Studio 在引用堆栈变量时不使用 EBP
- 堆栈变量或函数声明
- 访问堆栈变量的速度比取消引用指针慢
- 静态变量与堆栈变量:线程安全与堆栈大小
- 堆栈变量生存期好奇的例子
- 如何查找未初始化的堆栈变量
- 如何为堆栈变量分配内存