動態記憶體配置函式:malloc(), calloc(), realloc(), free().
void *malloc(size_t memsize)
自堆疊取memsize byte並回傳其起始位址。
void *calloc(size_t nelem, size_t elsize)
分配nelem個elsizebyte大小的空間,並將空間中內容設為0。回傳值為所分配的起始位址。
void *realloc(void *addr, size_t memsize)
重新分配memsizebyte的空間,並將原addr的內容複製到新位址。若新空間大於原空間,多出部份不作初始化;若新空間小於原空間,則多出內容會遺失。 回傳值為新分配之記憶體位址。
void free(void *addr)
釋放addr指向的記憶體空間。
以上為作動態記憶體配置時會用到的幾個函式,malloc()和calloc()在使用上較無特別需要注意之處。
free()在使用上則要注意不能對已被釋放的位址再作free(),這會導致segmentation fault。
realloc()是較可能產生誤用的函式,這次我也因為它吃了個大鱉,下場就是另外有十多支程式都要修改...(淚...)。
從字面看很容易理解,realloc()會"重新"分配指定大小的記憶體區塊,並將原位址的內容複製到新的位址。在實作上,系統判定若原位址後有足夠的空間,便直接以原位址調整記憶體區塊大小;若不足,則另尋足夠的空間分配。很多人(包括我)在用realloc()函式時都會忽略這一點,這時實作出的程式便是在"資料位址不會變動"的前提下運作的。這樣的程式在記憶體空間剩餘很多,且配置不集中的狀況下不會發生問題;除非系統對記憶體存取的控管夠嚴格。在一般x86系統上發生這種錯誤的機率較小,若在嵌入式系統中影響就很大了。
以我為實例,我所撰寫的程式會讀入一個文字檔案,有另一函式可以將檔案中某段文字替換為我所指定的值再顯示於螢幕上。在測試函式正確性時,因檔案作文字替換後和原來的字元數差異不大,所以一直到checkin入CVS系統後都未發現。今天有一個檔案需要插入大量文字,靈異現象就產生了:
存取該檔案、修改內容均正常,但最後要釋放記憶體便產生segmentation fault。
經上司幫忙找出問題後,發現因系統不會清除原位址之內容,而我所指定的位址也未更新為新配置的位址,所以在存取資料時除了最後一段內容均能正常操作。但該位址在系統的認定已經被釋放,所以當我最後呼叫free()時便產生segmentation fault。
由於程式上載已近一個月,其間有十多支引用此函式程式也都幾乎完成,所以我明天的工作便是將所有程式修正完成...。
當初小小的忽略造成這樣大的慘劇......。
慎之,慎之,不可再忘之...。
Recommend to Front page
瑣碎雜記(4)



Comment Permissions: Allow commenting