堆與棧 內存分配

一、內存分配問題

1.從靜態存貯區域分配,內存在編譯的時候已經分配好,這個內存在整個程序運行階段都存在。

2.從棧上創建,執行函數時,函數內的局部變量被分配到棧中,函數執行結束時自動釋放,這些內存空間配置於處理器的指令集中,效率高而靈活,但是內存容量有限

3.從堆上創建,也成爲動態內存分配,需要程序猿用malloc或者new來申請任意多少的內存空間(小於可用物理內存),函數執行完後也需要程序員自己進行free或者delete的操作來釋放內存,其特點是動態內存的生命週期有我們將決定,使用非常靈活,但問題也比較多


二、堆與棧

1、申請方式

  棧:無需申請,創建時系統自動分配,例如,聲明一個變量 int b;系統自動在棧中分配內存空間,,又例如,調用函數時,需要保存的變量。這種尤其是在遞歸調用時候,系統會分配一個棧的空間,後進先出,而後又由系統自動釋放空間,不會造成內存泄露。

 堆:需要程序員自己申請,C中用malloc,java中用new,並指出的大小。先進先出、後進後出。在調用結束後,C中需要程序員自己釋放,否則易造成內存泄露,而java的內存回收機制存在一定作用,但有可能仍發生內存泄露(短週期的對象被長週期的對象引用)。因爲內存泄露的問題,導致軟件越用越慢,重啓後恢復快速運行


2、申請後系統的相應

 棧: 只要棧的剩餘  空間大於申請空間,系統就會爲其分配棧空間,否則就會報異常--棧溢出。

 堆:首先應該知道,操作系統中會有一個記錄空閒區間的鏈表,當系統受到空間非配的申請時,就會遍歷該鏈表,尋找第一個空間大於申請空間的堆結點,然後將該結點從鏈表中刪除,並肩該空間非配給申請,。另外對於大多數熊,,這塊內存空間的首地址會記錄本次分配的大小,這樣,代碼中的free或者delete語句才能正確的釋放該塊空間。最後由於找到的堆結點的空間大小不會正好等於所申請空間的大小,因此會將剩餘的空間的那部分重新放入空閒鏈表中


3、申請大小的限制

 棧:在window下,棧是向低地址擴展的數據結構,是一塊連續的內存區域,這句話的意思是棧頂的地址和棧的容量是系統預先規定好的,在win下默認爲2M,可生情空間比較小

堆:堆是向高地址擴展的數據結構,是不連續的內存區域,這是由於系統用鏈表來存貯空閒地址的,自然是不連續的,而鏈表的遍歷方向由低地址向高地址,堆的大小受限於計算機系統中有效的虛擬內存,由此可見堆內存比較多大,而且比較靈活。


4、申請效率的比較

棧:系統分配,速度快,不收程序員控制

堆:有malloc/new 分配內存,速度相對較慢,易產生碎片(回收機制問題),不過勇氣來比較方便


5、存儲內容

 棧:在函數調用時,第一個進棧的是主函數中的下一條指令(函數調用語句的下一條可執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然後是函數中的局部變量,注意靜態變量是不入棧的。當本次函數調用結束後,局部變量先出棧,然後是參數,最後棧頂指針指向開始的內存,也就是主函數中下一條指令,程序由該點繼續運行

 堆:一般在頭部用一個字節存放堆的大小,具體內容由程序員來定


6、內存回收

棧內存:系統自動回收

堆內存:free或delete顯式回收,否則會造成內存泄露


使用棧就像去餐館裏吃飯,只管點菜(申請)、付錢吃飯(使用)、吃飽了就走人,不用收拾。很快捷方便但是自由度小

使用堆使用堆就像是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章