內存中堆和棧

  1. 棧是機器系統提供的數據結構, 現代計算機(串行執行機制)都直接在代碼底層支持棧的數據結構, 有專門的寄存器指向棧所在的地址, 有專門的機器指令完成數據入棧出棧的操作
  2. 棧的特點是效率高, 支持的數據類型有限, 一般是整數, 指針, 浮點數等系統直接支持的數據類型, 並不直接支持其他的數據結構
  3. 子程序的調用就是直接利用棧完成的, 機器的 call 指令裏隱含了把返回地址壓入棧, 然後跳轉至子程序地址的操作, 子程序中的 ret 指令則隱含了從堆棧中彈出返回地址並跳轉到返回地址的操作
  4. C/C++ 程序中的自動變量存入棧中, 這也就是爲什麼當函數返回時, 該函數的自動變量自動失效的原因
  5. 棧的特點: 快速, 高效, 但有限制, 數據不靈活, 對於進程/線程是唯一的
  6. 棧空間分靜態分配和動態分配兩種: 靜態分配是編譯器完成的, 比如自動變量(auto), 動態分配由 alloca 函數完成, 均自動釋放, 也就沒有釋放函數, 爲可移植的程序起見, 棧的動態分配操作是不被鼓勵的
  7. 函數調用時會在棧上有一系列的保留現場及傳遞參數的操作, 當一個函數調用完返回後它會釋放該函數中所有的棧空間, 棧的存儲地址連續, 不會產生內存碎片
  8. 棧的空間大小有限定, vc 中的缺省是2MB, 棧不夠用的情況一般是程序中分配了大量數組或遞歸函數層次太深
  9. 棧是先入後出的數據結構, 一般是由高地址向低地址方向生長
  10. 棧使用的是一級緩存, 通常被調用時處於存儲空間中, 調用完畢立即釋放

  1. 堆是由 C/C++ 函數庫提供的, 並不是由系統(無論是機器系統還是操作系統)支持的
  2. C中的 malloc, free 函數或C++中的 new, delete 函數維護了一套內部的堆數據結構
  3. 動態內存的分配: 先從內部堆中尋找可用的內存, 若失敗則利用系統調用來動態增加程序數據段的內存大小, 新分配得到的內存首先被組織進內部堆中去, 然後再以適當的形式返回給調用者
  4. 動態內存的釋放: 內存被返回內部堆結構中, 且可能會被適當的處理, 比如和其他空閒空間合併成更大的空閒空間, 以更適合下一次內存分配
  5. 堆的特點: 靈活, 方便, 數據適應面廣泛, 但由於堆中的數據需要通過指針進行存取, 效率低, 對於進程/線程不一定唯一, 不同堆分配的內存無法互相操作
  6. 堆空間的分配總是動態的, 雖然程序結束時, 所有的數據空間都會被操作系統回收, 但是精確的內存申請/釋放匹配是良好程序的基本要素, 否則可能產生內存泄漏
  7. 頻繁地調用 malloc 和 free 會產生內存碎片, 因爲 C 分配動態內存時是尋找匹配的內存的
  8. 堆內存區的地址是不連續的, 它是系統將空閒內存塊鏈接起來的鏈表, 用戶用 new/malloc 請求分配時, 找到第一個滿足大小要求的塊從鏈表中刪除此節點, 然後分給用戶
  9. 堆的數據結構可以被看成是一棵樹, 如堆排序
  10. 堆存放在二級緩存中, 生命週期由虛擬機的垃圾回收算法來決定, 並不是一旦成爲孤兒對象就能被回收, 所以調用這些對象的速度要相對來得慢一些

內存分配機制實際上相當於一個內存分配的緩衝池(Cache), 使用這套機制有如下若干原因:

  1. 系統調用可能不支持任意大小的內存分配, 有些系統的系統調用只支持固定大小及其倍數的內存請求(按頁分配), 這樣對於大量的小內存分配來說會造成浪費
  2. 系統調用申請內存可能是代價昂貴的, 可能涉及用戶態和內核態的轉換
  3. 隨意的內存分配和釋放操作會造成內存碎片
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章