儘管malloc和free所提供的記憶體分配介面比之brk和sbrk要容易許多,但在使用時仍然容易犯下各種程式設計錯誤。
理解malloc和free的實現,將使我們洞悉產生這些錯誤的原因以及如何才能避免此類錯誤。
to be continued 。。。。。。
malloc的實現很簡單。
它首先會掃瞄之前由free所釋放的空閒記憶體列表,以求找到尺寸大於或等於要求的一塊空閒記憶體。
(這取決於具體實現,採用的掃瞄策略會有所不同。例如first-fit或best-fit。)
如果這一記憶體塊的尺寸正好與要求相當,就把它直接返回給呼叫者。如果是一塊較大的記憶體,那麼將對其進行分割,在將一塊大小相同的記憶體返回給呼叫者的同時,把較小的那塊空閒記憶體塊保留在空閒列表中。
如果在空閒記憶體列表中根本找不到足夠大的空閒記憶體塊,那麼malloc會呼叫sbrk以分配更多的記憶體。為減少對sbrk的呼叫次數,malloc並未只是嚴格按所需位元組數來分配記憶體,而是以更大幅度(以虛擬記憶體頁大小的數倍)來增加prgram break,並將超出部分置於空閒記憶體列表。
至於free函式的實現則更為有趣。
當free將記憶體塊置於空閒列表之上使,是如何知曉記憶體塊大小的?
這是通過乙個小技巧來實現的。
當malloc分配記憶體塊時,會額外分配幾個位元組來存放記錄這塊記憶體大小的整數值。該整數字於記憶體塊 的起始處,而實際返回給呼叫者的記憶體位址恰好位於這一長度記錄位元組之後,如下圖所示。
當將記憶體塊置於空閒記憶體列表(雙向鍊錶)時,free會使用記憶體塊本身的空間來存放鍊錶指標,將自身新增到列表中,如下圖
隨著記憶體不斷地釋放和重新分配,空閒列表中的空閒記憶體和已分配的在用記憶體混雜在一起,如下圖
應該認識到,c語言允許程式建立指向堆中任意位置的指標,並修改其指向的資料,包括由free和malloc維護的記憶體塊長度、指向前一空閒塊和後一空閒塊的指標。輔之以之前的描述,一旦推究起隱晦難解的程式設計缺陷來,這無疑形同掉進了火藥桶。
例如,假設經由乙個錯誤指標,程式無意間增加了冠於一塊已分配記憶體的長度值,並隨即釋放這塊記憶體,free因之會在空閒列表記錄下這塊長度失真的記憶體。
隨後,malloc也許會重新分配這塊記憶體,從而導致如下場景:程式的兩個指標分別指向兩塊它認為互不相干的已分配記憶體,但實際上這塊記憶體缺相互重疊。
至於其他出錯情況則數不勝數。
要避免這類錯誤,應該遵守一下原則。
unix系統程式設計
popen pclose popen介面定義 include file popen const char command,const char type int pclose file stream popen函式會建立乙個管道,並且建立乙個子程序來執行shell,shell會建立乙個子程序來執行c...
UNIX系統程式設計1
man 你想查詢的內容 如果man你也不會用也不要緊,那你就 man man 一下,呵呵。只可惜好像還沒有翻譯成中文,對於像我這樣英文水平還有待提高的朋友來說讀起來有點麻煩。最後還有乙個好工具就是網路,有什麼不會的google一下好多問題都能解決。好,囉嗦的半天,說歸正傳,免得給大家造成光說不練的印...
Unix系統程式設計()brk,sbrk
在堆上分配記憶體 程序可以通過增加堆的大小來分配記憶體,所謂堆是一段長度可變的連續虛擬記憶體,始於程序的未初始化資料段末尾,隨著記憶體的分配和釋放而增減。通常將堆的當前記憶體邊界稱為 program break 下面也會學習一族函式brk,sbrk和malloc。調整program break br...