漫談 C++ 的 內存堆 實現原理
如果我來設計 C++ 的 內存堆 , 我會這樣設計 :
進程 首先會跟 操作系統 要 一塊大內存區域 , 我稱之為 Division , 簡稱 div 。
然後 , 將這塊 div 作為 堆 , 就可以開始 從堆裏分配 內存 了 。
堆裏 未分配 可使用 的 內存區域 稱之為 Free Space , 一開始的時候 , div 裏 只有一個 Free Space , 就是 整個 div 。
如果 只分配 不回收 的話 , div 裏 永遠都只有一個 Free Space 。 隨著 分配 和 回收 , div 裏會產生多個 Free Space 。
我們需要建立一張 堆表 來 記錄 Free Space , 這樣才能知道 每一次分配 應該 到 哪個 Free Space 裏 分配 。
堆表 應該是一個 鏈表 , 便於 插入 和 刪除 表項 。 表項 就是 Free Space , 或者說 表項 描述 Free Space 。 所以 表項 會包含 2 個 字段 , 一個是 Free Space 的 起始地址 , 另一個是 Free Space 的 結束地址 。
同時 還應該有一個 指針 , 指向 當前在用的 表項 , 一次分配 就是 在 當前表項 指向的 Free Space 裏分配 , 如果 當前 Free Space 的 大小 不足以分配本次申請的 內存塊大小 , 則 將指針 指向 當前 Free Space 的 下一個 Free Space 。 如果 下一個 Free Space 的 大小也不夠 , 那麽 就繼續指向 下一個 Free Space 。 如此循環 。
那如果 最後一個 Free Space 的大小也不夠的話 , 就需要向 操作系統 要 一個 新的 div 。 註意 , Free Space 只能屬於一個 div , 不能跨 div 。
如果 堆裏的 Free Space 比較多 , 那麽 如果 Free Space 大小不夠 , 有可能會連續找多個 Free Space 才找到 足夠大小的 Free Space , 這裏就產生了一個 性能問題 。
最壞的情況 , “從頭找到尾” , 到最後一個 Free Space 才足夠大小 。 但 , 這還不是最壞的 ^^ , 如果最後一個 Free Space 的大小也不夠的話 , 就要跟操作系統要一個 新的 div , 這好像要 “更壞” 一點 。 ^^
還有一個重要的問題需要考慮 , 就是 如果 跟操作系統要了 1 個以上的 div , 如果長期占用 , 這是一個不小的空間 。 那麽 , 要怎樣在 div 中的內存全部都已經回收 (整個 div 是一個 Free Space) 的時候 , 將 div 歸還操作系統呢 ?
可以通過一個 計數器 。 可以為每個 div 設置一個 計數器 , 同時在 堆表項 裏增加一個 字段 : Free Space 所在的 div 。
要記錄 堆 裏內存 分配 和 回收 狀況 , 需要 建立一張 堆表 來 記錄 堆
漫談 C++ 的 內存堆 實現原理