From:
1. https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
2. http://wp.mlab.tw/?p=312
-----------------------------------
The stack is the memory set aside as scratch space for a thread of execution. When a function is called, a block is reserved on the top of the stack for local variables and some bookkeeping data. When that function returns, the block becomes unused and can be used the next time a function is called. The stack is always reserved in a LIFO (last in first out) order; the most recently reserved block is always the next block to be freed. This makes it really simple to keep track of the stack; freeing a block from the stack is nothing more than adjusting one pointer.
The heap is memory set aside for dynamic allocation. Unlike the stack, there's no enforced pattern to the allocation and deallocation of blocks from the heap; you can allocate a block at any time and free it at any time. This makes it much more complex to keep track of which parts of the heap are allocated or free at any given time; there are many custom heap allocators available to tune heap performance for different usage patterns.
Each thread gets a stack, while there's typically only one heap for the application (although it isn't uncommon to have multiple heaps for different types of allocation).
To answer your questions directly:
To what extent are they controlled by the OS or language runtime?
The OS allocates the stack for each system-level thread when the thread is created. Typically the OS is called by the language runtime to allocate the heap for the application.
What is their scope?
The stack is attached to a thread, so when the thread exits the stack is reclaimed. The heap is typically allocated at application startup by the runtime, and is reclaimed when the application (technically process) exits.
What determines the size of each of them?
The size of the stack is set when a thread is created. The size of the heap is set on application startup, but can grow as space is needed (the allocator requests more memory from the operating system).
What makes one faster?
The stack is faster because the access pattern makes it trivial to allocate and deallocate memory from it (a pointer/integer is simply incremented or decremented), while the heap has much more complex bookkeeping involved in an allocation or deallocation. Also, each byte in the stack tends to be reused very frequently which means it tends to be mapped to the processor's cache, making it very fast. Another performance hit for the heap is that the heap, being mostly a global resource, typically has to be multi-threading safe, i.e. each allocation and deallocation needs to be - typically - synchronized with "all" other heap accesses in the program.
A clear demonstration:
變數會佔用記憶體,記憶體分為三個部份來存這些變數,分別是global、stack與heap。
global:
用來放全域變數、靜態變數(static)等等。
stack:
台灣正體中文稱為堆疊,大陸叫做棧。
區域變數、函式的參數與函式的位址等等,由系統管理,必須在編譯時期為已知。這些變數的回收會發生在它從堆疊pop出去的時候,因為個數、大小什麼的都是已知,所以系統知道怎麼進行配置與回收。
heap:
台灣正體中文稱為堆積,大陸叫做堆。
這裡的記憶體由使用者負責進行回收,配置則是由malloc或是new來負責。使用這裡的記憶體主要是用在編譯時期還不知道大小或個數的變數。例如說,你需要用一個陣列,這個陣列的大小要在執行的時候由使用者的輸入來決定,那你就只能使用動態配置,也就是把這個陣列配置在heap中。
stack與heap在記憶體中的配置狀況可以參考這張圖(http://www.geeksforgeeks.org/archives/14268):
我們也做一個小小的實驗吧:
address of a1 is 0x7fff4e62c554
address of a2 is 0x7fff4e62c550
address of a3 is 0x7fff4e62c54c
address of a4 is 0x7fff4e62c548
address of a5 is 0x7fff4e62c544
address of b1 is 0x7fff4e62c538
value of b1 is 0x417a010
address of b2 is 0x7fff4e62c530
value of b2 is 0x417a030
address of b3 is 0x7fff4e62c528
value of b3 is 0x417a050
address of b4 is 0x7fff4e62c520
value of b4 is 0x417a070
可以發現,a1到a5的記憶體位址是由大而小,也就是由高而低。而b1到b4的所指的位址(在heap)是由小而大,也就是由低而高,b1到b4本身的位址(在stack)則是由高而低。