C內存分配函數的大多數實現將存儲每個塊的記帳信息,無論是在線的還是單獨的。
一種典型的方式(在線)是實際分配一個頭和你想要的內存,填充到最小的大小。例如,如果您請求20個字節,系統可能會分配一個48字節的塊:
- 16字節頭,包含大小、特殊標記、校驗和、指向下一個/前一個塊的指針等。
- 32字節數據區域(20個字節被填充到16的倍數)。
然后提供給您的地址是數據區域的地址。然后,當你解放了這個街區,free
只需取下你給它的地址,假設你沒有把地址或它周圍的內存塞滿,就在它前面檢查會計信息。從圖形上看,這將遵循以下方針:
____ The allocated block ____
/ \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
^
|
+-- The address you are given
請記住頭部的大小和填充是完全定義的(實際上,整個事情都是由實現定義的)。(A)但在線會計選項是常見的)。
會計信息中存在的校驗和以及特殊標記常常是導致錯誤的原因,如“內存場損壞”或“雙空閑”(如果您覆蓋它們或釋放它們兩次)。
填充(使分配更有效)是為什么有時可以在請求空間的末尾寫一點內容而不會引起問題(盡管如此,不要這樣做,這是未定義的行為,僅僅因為它有時工作,并不意味著可以這樣做)。
(A)我編寫了malloc
在嵌入式系統中,不管您想要什么(這是系統中最大結構的大小),只要您請求128字節或更少(請求更多將滿足空返回值),就會得到128個字節。使用一個非常簡單的位掩碼(即不在線)來決定是否分配了128字節塊。
我開發的其他程序也有不同的池,用于16字節塊、64字節塊、256字節塊和1K塊,同樣使用位掩碼來決定所使用或可用的塊。
這兩個選項都設法減少了會計信息的開銷,并提高了malloc
和free
(解放時不需要合并相鄰的區塊),特別是在我們工作的環境中。