Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the stack address grow towards decreasing memory addresses?

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?

like image 445
Jestin Joy Avatar asked Dec 30 '10 07:12

Jestin Joy


People also ask

Why does the stack grow downwards in memory?

When a new local variables is declared, more stack memory is allocated for that function to store the variable. Such allocations make the stack grow downwards. After the function returns, the stack memory of this function is deallocated, which means all local variables become invalid.

How does stack grow in memory?

This stack grows downward from its origin. The stack pointer points to the current topmost datum on the stack. A push operation decrements the pointer and copies the data to the stack; a pop operation copies data from the stack and then increments the pointer.

Which direction does the runtime stack grow?

It grows down because the memory allocated to the program has the "permanent data" i.e. code for the program itself at the bottom, then the heap in the middle.


2 Answers

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.

like image 190
mmx Avatar answered Sep 18 '22 19:09

mmx


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.

like image 29
zwol Avatar answered Sep 21 '22 19:09

zwol