為什麼要有堆區和棧區呢?

如果局部變數放堆區,不用時就free掉,似乎也沒什麼問題啊


因為結構化語言里函數(子程序)調用最方便的實現方式就是用棧,以至於現在絕大部分晶元都對棧提供晶元級的硬體支持,一條指令即可搞定棧的pop操作。棧的好處是:方便、快、有效避免內存碎片化。棧的問題是:不利於管理大內存(尤其在16位和32位時代)、數據的生命周期難於控制(棧內的有效數據通常是連續存儲的,所以pop時後申請的內存必須早於先申請的內存失效),所以棧不利於動態地管理並且有效地利用寶貴的內存資源。於是我們有了堆。。。


覺得堆和棧沒區別是因為覺得他們的分配和回收沒什麼區別,但實際上不是這樣的。棧只要上下移動esp就可以實現內存的分配和回收。堆就不行了,需要一套分配策略,要防止出現大量小碎片。為了加快分配速度可能還會有快表。回收的時候也會根據大小回收至不同節點方便分配。具體細節我也不清楚:( 不過比起棧來肯定要複雜得多。


棧操作快啊,sub esp後就能用了。堆的話還要先malloc,會進到操作系統的堆實現,比如windows的ntdll。不是一個數量級啊。


我記得棧的分配是編譯期決定的,堆的話需要運行時去申請。

除去申請的開銷,char a其實只佔用1位元組,char* a卻需要在棧上有4/8位元組的指針。

而且理論上零散的小變數分配在堆上的話,訪問可能會慢些(cpu可能能把這個抹平)


效率問題。局部變數如果放到堆里,手動分配不算,每次離開作用域,程序員們都需要手動free掉,一個變數忘記free還好,遞歸的時候忘記free該有多壯觀...

對於計算機來講函數調用局部變數分配由sub 0x08 %rsp一條命令變成了malloc兩個函數調用,效率慢不止百倍。


malloc出來的地址(指針)需要一個可以預測的地方保存起來以供使用,否則你需要malloc一塊新內存來保存這個地址,新內存的地址同樣需要內存來保存,則子子孫孫無窮匱也


舉個例子:

一個進程,加上主函數一共有4個函數,

main{

函數A

函數B

函數C

}

如果在堆區分配,那麼四個函數都執行完再回收,則佔用很大的空間。如果執行完函數後立刻回收這個函數的空間,因為堆的特性,需要增加額外的機制,會很麻煩。

使用棧就可以解決上面的問題了~請查看數據結構中棧的定義及使用意義

另外,堆用來進行空間分配(連續與非連續),是二級緩存方式,這一塊比較麻煩,如有興趣,可研究一下 Linux內核的 slab機制與夥伴系統,深入理解動態分配原理~


根據個人粗糙的理解

棧是用來實現函數調用的傳遞過程參數、存儲返回信息、保存寄存器用於恢復,以及本地存儲!

堆就是一個進程虛擬存儲器區域!虛擬存儲器你知道吧?它是主存的抽象,處理主存和磁碟的交互!

總的來說它們是分工合作的!

除了局部變數它們還要做很多事啊!


性能問題,因為現在CPU的處理模型就是棧,而且棧上的變數命中率比堆高到不知哪裡去了


為了提高性能罷了

棧上的局部變數,只要改動下指針就可以;棧空間有嚴格的先進後出規律,管理起來非常方便

而堆的申請很麻煩,釋放回收就更麻煩了。對此,你自己手動模擬下堆和棧上隨機申請-釋放空間操作就行了


恩,可以坐火車的也都可以沿著鐵軌步行.


推薦閱讀:

如何將一個有序的數組隨機排序?
從事C#開發兩年,25歲轉Cocos2d-x開發,會不會太晚?
C/C++ 中 bool 相比於 char 有什麼優勢?為什麼要設立 bool 類型?
二級C習題10.10為什麼選C?
有必要在寫 C++ 時避免隱式轉換嗎?

TAG:編程 | CC | 計算機組成原理 |