為什麼要有堆區和棧區呢?
01-07
如果局部變數放堆區,不用時就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++ 時避免隱式轉換嗎?