1. 程式人生 > >Unix系統編程()在堆上分配內存

Unix系統編程()在堆上分配內存

color 所有 地址 lib 堆內存 多線程 brk break 處的

在堆上分配內存:malloc和free

一般情況下,C程序使用malloc函數族在堆上分配和釋放內存。較之brk和sbrk,這些函數具備不少優點:

屬於C語言標準的一部分

更易於在多線程程序中使用

接口簡單,允許分配小塊內存

允許隨意釋放內存塊,它們被維護於一張空閑內存列表中,在後續內存分配調用時循環使用

malloc函數在堆上分配參數size字節大小的內存,並返回指向新分配內存起始位置處的指針,其所分配的內存未經初始化。

#include <stdlib.h>
void *malloc(size_t size);    /* Returns pointer to allocated memory on sucess, or NULL on error 
*/

由於malloc的返回類型為void*,因而可以將其付賦給任意類型的C指針。malloc返回內存塊所采用的的字節對齊方式,總是適宜於高效訪問任何類型的C語言數據結構。在大多數硬件架構上,這意味著malloc是基於8字節或16字節邊界來分配內存的。

SUSv3規定:調用malloc(0)要麽返回NULL,要麽是一小塊可以(並且應該)用free釋放的內存。Linux的malloc(0)遵循的是後者。

如果無法再分配內存(或許是因為已經達到了program break所能達到的地址上限),則malloc返回NULL,並設置errno以返回錯誤信息。

雖然分配內存失敗的可能性很小,但所有對malloc以及後續提及的相關函數的調用都應對返回值進行錯誤檢查。

free函數釋放ptr參數所指向的內存塊,該參數應該是之前由malloc,或者後續描述的其他堆內存分配函數之一所返回的地址。

#include <stdlib.h>
void free(void *ptr);

一般情況下,free並不降低program break的位置,而是將這塊內存填加到空閑內存列表中,供後續的malloc函數循環使用。這麽做是出於以下幾個原因。

被釋放的內存塊通常會位於堆的中間,而非堆的頂部,因而降低program break是不可能的。

它最大限度地減少了程序必須執行的sbrk調用次數。

在大多數情況下,降低program break的位置不會對那些分配大量內存的程序有多少幫助,因為它們通常傾向於持有已經分配內存或是反復釋放和重新分配內存,而非釋放所有內存後再持續運行一段時間。

如果傳給free的是一個空指針,那麽函數將什麽都不做。(換句話說,給free傳入一個空指針並不是錯誤代碼。)

在調用free後對參數ptr的任何使用,例如將其再次傳遞給free,將產生錯誤,並可能導致不可預知的結果。

Unix系統編程()在堆上分配內存