
What and where are the stack and heap? - gs7
http://stackoverflow.com/a/80113
======
derefr
If this article is news for you, this might be a helpful corollary:

 _Threads_ and _processes_ are both units of execution. (A unit of execution
is like a virtual processor -- a separate instruction pointer that makes its
way through your code, doing computations and following jumps.)

Both _threads_ and _processes_ have their own stacks. You reserve a new stack
when you fork(), or when you spawn a thread.

But only _processes_ have their own heaps. In fact, this is the defining
distinction between threads and processes: if you're sharing your heap with
other execution-units, you're a thread; if you have your own isolated heap,
you're a separate process.

~~~
fiatmoney
You can also mmap a chunk of memory and share it between processes.

~~~
blibble
also there's nothing stopping a thread having its own logical heap.

grandparent is confusing the concept of address space and heap.

~~~
derefr
Address spaces are just an _implementation detail_. You can have both
processes and threads on an architecture without any such concept. The _point_
\-- the theory -- behind processes, is to separate your heap from your
neighbor's heap, so pointers in your heap pointing at addresses in theirs
won't be valid, or vice-versa. You could do this with virtual-memory mapping,
memory segmentation, tagged pointers, domain-taint as static type checking,
etc. and you'd get the same result.

Why only the heap? Since pointers on the stack can only (coherently) point
into the same stack, or to the heap--and pointers on the heap can't point back
into any stack--then stacks are already isolated. (Registers follow the same
isolation rules as stack entries, if you want a register-machine.)

The reason you want to isolate your heap in the first place, the benefit you
get, is that an isolated heap is an isolated graph for any garbage-collection
system to pass over, and an isolated set-of-blocks-of-bytes for an exception
to throw out or the OOM killer to discard. As soon as you have an isolated
heap, in other words, you get all the _practical_ advantages that come with
running in a separate process.

If you implement a bytecode interpreter that can concurrently switch between
several instruction pointers with their own _stacks_ , then you've implemented
green-threads. If each of those instruction pointers also has their own _heap_
, you've implemented virtual processes.

~~~
haberman
If you are programming to the level of abstraction of an ISO C or C++ program
(or a higher-level language/abstraction), then the stack and heap are your
primitives and address spaces are an implementation detail.

If you are programming to the level of abstraction of POSIX, then address
spaces are fundamental and the stack and heap are just convenience interfaces
around mmap().

The fact that the StackOverflow question was asking for more OS-level details
than the existing explanations they had found suggests that this is the time
to provide actual implementation details instead of answering in more
abstractions.

~~~
derefr
I'm not talking about programming, I'm talking about computer science. A heap
(really, an object reference digraph) is a mathematical object that you can
prove theorems about. An address space is just one way to isolate a block of
memory, a way to enforce _on a Von Neumann architecture_ the preconditions
that allow for that mathematical object to be instantiated and manipulated.
Not every machine is an x86 with an MMU.

~~~
haberman
> A heap (really, an object reference digraph) is a mathematical object that
> you can prove theorems about.

So is a Pseudo-Riemannian manifold. But neither of these is what the person
was asking questions about. They were asking about programming on computers
with operating systems.

------
terhechte
Uli Kusterer has a really good, very graphical, description in his "Masters of
the Void" series, too:

[http://masters-of-the-void.com/book5.htm](http://masters-of-the-
void.com/book5.htm)

------
com2kid
I'd argue against there being "only 1 heap". Only one OS provided heap, sure,
but in C++ it is quite common to overload new and allocate into a separate
statically declared buffer.

(See: Video games!"

And, as usual, no mention was made of static allocations! :(

~~~
kabdib
Oh yes.

Heaps for allocating textures. Object-type-specific heaps for things like
sounds and models. "Smart" heaps that can invalidate their contents under
memory pressure (and maybe automatically bring stuff back in, possibly
speculatively). Heaps that are good for lots of small allocations. Heaps that
either do or do not allow multiple threads to use them. Heaps that are
position-independent and that can be used in shared memory buffers (which can
be mapped to different addresses in different processes). I could go on.

I wrote a lot of the memory management stuff for the Apple Newton, and it had
several types of heaps:

\- A common "Macintosh-like" heap with both fixed and sliding blocks (even
with a VM system managing the page for you, fragmentation matters when memory
is tight). Most threads played in this heap, and keeping it sane was kind of
hard.

\- A couple of heaps for the kernel, for managing its objects (it's been a
while, I don't remember why there was more than one).

\- A heap that could supply (limited) amounts of memory for interrupt
handlers.

\- The NewtonScript object heap (owned by the NewtonScript environment).

I'm pretty sure there were a couple more heaps, but I've forgotten the
details. Our main worry was fragmentation, and I'd say that things probably
weren't segmented enough and that we needed even more heaps than we shipped
with.

A heap is just a data structure. Ain't nothing magic.

~~~
yongjik
I wouldn't call a heap a "data structure", though. It will lead to mighty
confusion, as heap-the-data-structure has nothing to do with heap-in-which-
you-allocate-memory.

------
mtdewcmu
The stack is a concept that's built into the CPU to handle function calls.
Every time you call a function, there is a return address that needs to be
stored. Since you need to hang on to a return address for every function that
is currently in progress, and you use them in the reverse order that they were
stored, what you need is exactly a stack. The stack is usually (always?)
located at the top of memory and grows down. In addition to return addresses,
it can be used to store data associated with an in-progress function, like
arguments, local variables, and cpu state data that needs to be temporarily
stored.

So that's the stack. The concept of the heap, on the other hand, isn't built
into the CPU, and is sort of a vague abstraction implemented by programming
languages. The first thing to know about how it differs from the stack: it's
not a stack. Stack reads and writes follow LIFO; reads and writes to the heap
can potentially be in any order. The heap is usually (always?) located close
to the bottom of memory, and grows up. So the stack and heap grow toward each
other. At the lowest level, the heap is basically just memory that can be used
as the application sees fit. Data on the heap isn't inherently tied to an in-
progress function call, so it can last indefinitely (at least, until the
process ends). The programming language or the C library typically provide a
means to subdivide the heap memory into discrete blocks as needed in response
to an explicit or implicit memory allocation request (e.g. malloc(), new), and
keep track of what memory is available and what is currently allocated.

Differences between the stack and the heap:

* the stack is limited in size, so it is easy to overflow and crash if you try to store too much data there. the heap, in contrast, is designed to grow as much as needed * the stack is managed primarily by instructions built into the cpu. the heap is managed by library calls and system calls * the difference in speed between the two refers to the speed of allocating or freeing a chunk. the stack can inherently do this quickly, because the location for the memory is predetermined. since the heap can do allocations and deallocations in any order, finding memory for blocks is inherently more complicated and slower. * since the fundamental purpose of the stack is to store data about in-progress functions, it follows that every executing thread has its own stack and usually only accesses its own. the heap, on the other hand, has no association to a thread of execution, which consequently means that multiple threads can share the same heap, and locking and synchronization must come into play when the heap metadata has to change. The locking is typically transparent, but the net result is to make allocations and deallocations even slower in threaded code.

~~~
skj
The concept of the stack is built into the CPU? That's news to me... I mean,
I'm not a hardware guy so I guess I could have been misinformed, but I thought
it was something the OS managed as a reserved chunk of main memory (like the
heap).

Registers are built into the CPU, but that's a different thing than the stack.

~~~
a-priori
In the x86 family anyway, it's kinda-sorta 'built in'. It is possible to avoid
using the stack -- it's done in interrupt handlers which do not have a stack
of their own and must avoid clobbering it -- but most code uses it fairly
frequently and there are many auxiliary instructions that push and pop from
the stack.

In addition to some explicit stack-related instructions like PUSH/POP,
PUSHF/POPF, PUSHA/POPA, PUSHAD/POPAD and many others, certain other operations
assume you have a valid stack and act on it. For example, the CALL function
(used to call a procedure/function) will push a return address to the stack,
and RET (used to return to the caller at the end of a procedure/method) will
pop the return address to the stack and jump to it.

These instructions are fairly essential to the function calling conventions
for typical code, enough that it's reasonable to say that the concept of the
stack is 'built into' x86 processors.

Partly this is because the x86 processor is a beast with an instruction for
everything. Other more RISCy architectures tend to not bake in the stack, and
instead you use any general-purpose register as a stack pointer and manipulate
it manually with regular instructions.

[http://en.wikipedia.org/wiki/X86_instruction_listings](http://en.wikipedia.org/wiki/X86_instruction_listings)

~~~
joezydeco
Lots of smaller microprocessors _live_ by the stack. Aside from the typical
JSR/RET stuff with pushing the program counter, you can also do very
lightweight programming tricks with the stack pointer.

For example, you can pass arguments to an assembly subroutine by putting the
data right after the JSR call. The called subroutine pulls the args by
manipulating the stack pointer and the return will jump PC after the argument
date.

You can also use stack pointer to briefly allocate a small amount of memory
for scratch inside a routine instead of allocating heap or using globals. This
is a big help on small micros where you _might_ get a scratch register or two
normally but now you need 4 or 8 bytes for a quick piece of work.

------
pramodliv1
I remember the first time when I worked on multithreaded C++ project. I
allocated a structure on the stack and passed its address to a queue which was
received by another thread and the inevitable segfault happened. My mistake
provided a lot of laughs for the entire team.

Also see [http://stackoverflow.com/questions/8468210/stack-vs-
heap-c](http://stackoverflow.com/questions/8468210/stack-vs-heap-c)

~~~
ksk
I understand what you meant but to be a bit pedantic, you can freely allocate
structures on the stack and pass it around. You might have heard of a few of
them .. cout, cin :P

