4 ms·
As someone who teaches this stuff at university, I see students getting confused every single year by how textbooks draw memory. The problem is mostly visual, n
by bignerd_95 11mo ago
As someone who teaches this stuff at university, I see students getting confused every single year by how textbooks draw memory. The problem is mostly visual, not conceptual.
Most diagrams in books and slides use an old hardware-centric convention: they draw higher addresses at the top of the page and lower addresses at the bottom. People sometimes justify this with an analogy like “floors in a building go up,” so address 0x7fffffffe000 is drawn “higher” than 0x400000.
But this is backwards from how humans read almost everything today. When you look at code in VS Code or any other IDE, line 1 is at the top, then line 2 is below it, then 3, 4, etc. Numbers go up as you go down. Your brain learns: “down = bigger index.”
Memory in a real Linux process actually matches the VS Code model much more closely than the textbook diagrams suggest.
You can see it yourself with:
cat /proc/$$/maps
(pick any PID instead of $$).
...
[0x00000000] lower addresses
...
[0x00620000] HEAP start
[0x00643000] HEAP extended ↓ (more allocations => higher addresses)
...
[0x7ffd8c3f7000] STACK top (<- stack pointer)
↑ the stack pointer starts here and moves upward
(toward lower addresses) when you push
[0x7ffd8c418000] STACK start
...
[0xffffffffff600000] higher addresses
...
The output is printed from low addresses to high addresses. At the top of the output you'll usually see the binary, shared libs, heap, etc. Those all live at lower virtual addresses. Farther down in the output you'll eventually see the stack, which lives at a higher virtual address. In other words: as you scroll down, the addresses get bigger. Exactly like scrolling down in an editor gives you bigger line numbers.
The phrases “the heap grows up” and “the stack grows down” aren't wrong. They're just describing what happens to the numeric addresses: the heap expands toward higher addresses, and the stack moves into lower addresses.
The real problem is how we draw it. We label “up” on the page as “higher address,” which is the opposite of how people read code or even how /proc/<pid>/maps is printed. So students have to mentally flip the diagram before they can even think about what the stack and heap are doing.
If we just drew memory like an editor (low addresses at the top, high addresses further down) it would click instantly. Scroll down, addresses go up, and the stack sits at the bottom. At that point it’s no longer “the stack grows down”: it’s just the stack pointer being decremented, moving to lower addresses (which, in the diagram, means moving upward).
- 1718627440 11mo agoThat's how stacks on my desk grow and how everything grows in reality. I wouldn't numerate stacked things on my desk from the top, since this constantly changes. You also wouldn't name the first branch of a tree (the plant) to be the top-most one. In your example "the stack grows down", seems to be wrong in the image.
- bignerd_95 11mo agoThanks! I tried to rewrite the final sentence
- 1718627440 11mo agoYeah, but does that really help? The phrases "growing down/up" still exist and now you defined them to mean the opposite. This issue still didn't go away, since heap and stack still grow in different directions. Can't you just start drawing from the bottom of the blackboard, and it will be obvious? Coordinate systems also typically work that way.
- ofalkaed 11mo agoStarting at the bottom of the blackboard would be backwards from how it prints in the terminal when you cat /proc/<pid>/maps.
- 1718627440 11mo agoThe way it's printed in the terminal is honestly backwards to me. This seams to only come from the scroll direction of the terminal, and because this is not a drawing, but a simple list. Every other tool like a debugger show it in the opposite direction and in all illustrations I have read it's that way too.
- bignerd_95 11mo agoSo you use debuggers. Good. Then you can confirm that the program counter is incremented after each instruction, and that you read assembly from top to bottom. That means smaller addresses are at the top and larger addresses are at the bottom. This matches my layout, and it also matches what you see in the terminal in /proc/<pid>/maps.