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