为什么堆栈地址会逐渐减少内存地址?

Jes*_*Joy 31 stack callstack memory-management virtual-memory

我在课本中读到堆栈通过减少内存地址而增长; 也就是说,从较高地址到较低地址.这可能是一个糟糕的问题,但我没有把这个概念弄好.你可以解释吗?

Meh*_*ari 57

首先,它取决于平台.在某些体系结构中,堆栈从地址空间的底部分配并向上增长.

假设像x86这样的架构从地址空间的顶部向下增长,那么这个想法非常简单:

===============     Highest Address (e.g. 0xFFFF)
|             |
|    STACK    |
|             |
|-------------|  <- Stack Pointer   (e.g. 0xEEEE)
|             |
.     ...     .
|             |
|-------------|  <- Heap Pointer    (e.g. 0x2222)
|             |
|    HEAP     |
|             |
===============     Lowest Address  (e.g. 0x0000)
Run Code Online (Sandbox Code Playgroud)

要增加堆栈,您将减少堆栈指针:

===============     Highest Address (e.g. 0xFFFF)
|             |
|    STACK    |
|             |
|.............|  <- Old Stack Pointer (e.g. 0xEEEE)
|             |
| Newly       |
| allocated   |
|-------------|  <- New Stack Pointer (e.g. 0xAAAA)
.     ...     .
|             |
|-------------|  <- Heap Pointer      (e.g. 0x2222)
|             |
|    HEAP     |
|             |
===============     Lowest Address    (e.g. 0x0000)
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,成长组,我们已经降低堆栈指针从0xEEEE在0xAAAA到,而增长堆,你必须增加堆指针.

显然,这是内存布局的简化.实际的可执行文件,数据部分......也加载到内存中.此外,线程有自己的堆栈空间.

你可能会问,为什么堆栈会向下生长.好吧,正如我之前所说的,一些架构反过来,使堆向下增长,堆栈向上增长.将堆栈和堆放在相对的两侧是有意义的,因为它可以防止重叠并允许两个区域自由增长,只要有足够的可用地址空间即可.

另一个有效的问题可能是:程序是否应该减少/增加堆栈指针本身?架构如何将一个架构强加给程序员?为什么它不依赖程序,因为它依赖于架构?虽然你几乎可以打架构并以某种方式摆脱你的筹码在相反的方向,一些指令,特别是callret该修改堆栈指针直接将要承担另一个方向,弄得一团糟.

  • 单独的ASCII艺术+0.5.:)但是,在回答"如何"时,这根本不能很好地回答"为什么".是什么让这种方式定义堆栈如此常见和/或有用? (5认同)
  • @cHao:添加了几个段落来解决这个问题. (2认同)
  • @Mehrdad Afshari有些文章说它是因为我们可以保持偏移非负,因为堆栈向下增长 (2认同)
  • @Mehrdad Afshari要访问堆栈帧的内容,我们只需要使用非负偏移值(因为堆栈从高到低增长,堆栈的顶部始终是最低地址).Steven S.Muchnick的高级编译器设计和实现第122页 (2认同)

zwo*_*wol 23

如今,这很大程度上是因为它已经以这种方式进行了很长时间,很多程序都认为它是这样完成的,而且没有真正的理由去改变它.

当恐龙在地球上漫游而计算机有8kB的记忆时,如果幸运的话,这是一个重要的空间优化.你把堆栈的底部放在内存的最顶端,逐渐减少,然后将程序及其数据放在最底层,malloc区域越来越大.这样,堆栈大小的唯一限制是程序+堆的大小,反之亦然.如果堆栈开始于4kB(例如)并且长大,那么堆永远不会超过4kB(减去程序的大小),即使程序只需要几百个字节的堆栈.