为什么堆栈地址会朝着内存地址减少的方向增长?

发布于 2024-10-09 20:19:43 字数 73 浏览 5 评论 0原文

我在教科书中读到,堆栈通过减少内存地址来增长;即从高地址到低地址。这可能是一个糟糕的问题,但我没有正确理解这个概念。你能解释一下吗?

I read in text books that the stack grows by decreasing memory address; that is, from higher address to lower address. It may be a bad question, but I didn't get the concept right. Can you explain?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

南街九尾狐 2024-10-16 20:19:43

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

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

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

要增长堆栈,您需要减少堆栈指针:

===============     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)

如您所见,为了增长堆栈,我们减少了 /em> 堆栈指针从 0xEEEE 到 0xAAAA,而要增长堆,则必须增加堆指针。

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

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

另一个有效的问题可能是:程序不是应该减少/增加堆栈指针本身吗?一种架构如何将一种架构强加给程序员?为什么它不像程序那样依赖于体系结构?
虽然您几乎可以对抗架构并以某种方式以相反的方向摆脱堆栈,但一些直接修改堆栈指针的指令,特别是 callret 将假设另一个方向,弄得一团糟。

First, it's platform dependent. In some architectures, stack is allocated from the bottom of the address space and grows upwards.

Assuming an architecture like x86 that stack grown downwards from the top of address space, the idea is pretty simple:

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

To grow stack, you'd decrease the stack pointer:

===============     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)

As you can see, to grow stack, we have decreased the stack pointer from 0xEEEE to 0xAAAA, whereas to grow heap, you have to increase the heap pointer.

Obviously, this is a simplification of memory layout. The actual executable, data section, ... is also loaded in memory. Besides, threads have their own stack space.

You may ask, why should stack grow downwards. Well, as I said before, some architectures do the reverse, making heap grow downwards and stack grow upwards. It makes sense to put stack and heap on opposite sides as it prevents overlap and allows both areas to grow freely as long as you have enough address space available.

Another valid question could be: Isn't the program supposed to decrease/increase the stack pointer itself? How can an architecture impose one over the other to the programmer? Why it's not so program dependent as it's architecture dependent?
While you can pretty much fight the architecture and somehow get away your stack in the opposite direction, some instructions, notably call and ret that modify the stack pointer directly are going to assume another direction, making a mess.

不喜欢何必死缠烂打 2024-10-16 20:19:43

如今,这主要是因为很长一段时间以来都是这样做的,并且许多程序都假设它是这样做的,并且没有真正的理由来改变它。

当恐龙在地球上漫游时,计算机拥有 8kB 内存(如果幸运的话),这是一个重要的空间优化。您将堆栈底部放在内存的最顶部,向下增长,将程序及其数据放在最底部,malloc 区域向上增长。这样,堆栈大小的唯一限制是程序+堆的大小,反之亦然。如果堆栈从 4kB(例如)开始并不断增大,则即使程序只需要几百字节的堆栈,堆也永远不会大于 4kB(减去程序的大小)。

Nowadays it's largely because it's been done that way for a long time and lots of programs assume it's done that way, and there's no real reason to change it.

Back when dinosaurs roamed the earth and computers had 8kB of memory if you were lucky, though, it was an important space optimization. You put the bottom of the stack at the very top of memory, growing down, and you put the program and its data at the very bottom, with the malloc area growing up. That way, the only limit on the size of the stack was the size of the program + heap, and vice versa. If the stack instead started at 4kB (for instance) and grew up, the heap could never get bigger than 4kB (minus the size of the program) even if the program only needed a few hundred bytes of stack.

简单 2024-10-16 20:19:43

Man CLONE :child_stack 参数指定子进程使用的堆栈位置。由于子进程和调用进程可能共享内存,因此子进程不可能与调用进程在同一堆栈中执行。因此,调用进程必须为子堆栈设置内存空间,并将指向该空间的指针传递给clone()。在运行 Linux 的所有处理器(HP PA 处理器除外)上,堆栈都是向下增长的,因此 child_stack 通常指向为子堆栈设置的内存空间的最顶层地址。

Man CLONE : The child_stack argument specifies the location of the stack used by the child process. Since the child and calling process may share memory, it is not possible for the child process to execute in the same stack as the calling process. The calling process must therefore set up memory space for the child stack and pass a pointer to this space to clone(). Stacks grow downward on all processors that run Linux (except the HP PA processors), so child_stack usually points to the topmost address of the memory space set up for the child stack.

送舟行 2024-10-16 20:19:43

在 x86 上,堆栈向内存地址递减方向增长的主要原因是 PUSH 指令递减堆栈指针:

递减堆栈指针,然后将源操作数存储在堆栈顶部。

参见第 17 页。 英特尔® 64 和 IA-32 架构软件开发人员手册

On x86, the primary reason the stack grows toward decreasing memory addresses is that the PUSH instruction decrements the stack pointer:

Decrements the stack pointer and then stores the source operand on the top of the stack.

See p. 4-511 in Intel® 64 and IA-32 ArchitecturesSoftware Developer’s Manual.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文