malloc(記憶體配置)
/ MAL-ock /
malloc 是 C 中動態記憶體的主力。它的名字是 memory allocate(記憶體配置)的縮寫。你交給它一個數字——你要多少個位元組——它就回傳一塊至少這麼大的記憶體的位址,這塊記憶體現在歸你使用。可以想像走到寄物櫃櫃台說我需要一個能放 200 個箱子的櫃子,然後拿到一把鑰匙。鑰匙就是指標;櫃子就是你的區塊。
精確地說:malloc(size) 接受一個以位元組為單位的大小(型別為 size_t),回傳一個 void *——指向一塊至少那麼多位元組、未初始化區塊之第一個位元組的通用指標,且對任何物件都適當對齊。有兩點至關重要。第一,內容未初始化:malloc 不會把記憶體清零,所以裡面是先前殘留的任意位元組。在你寫入前就讀取它會得到垃圾值,是個錯誤。第二,malloc 可能失敗。若系統無法滿足請求,它回傳 NULL,而解參考該 NULL 會當掉。所以實務上的固定模式永遠是:呼叫 malloc、檢查是否為 NULL、然後先寫再讀。malloc(0) 是被允許的,但可能回傳 NULL 或一個你仍然不可解參考的唯一指標。
你呼叫的每一次 malloc 都是一筆債:這塊區塊會一直被保留,直到你對那個確切的指標呼叫 free()。malloc 與 free 成對出現。弄丟指標就造成記憶體洩漏;釋放兩次就是重複釋放;釋放後又使用就是釋放後使用。由於 malloc 回傳 void *,在 C 中它會自動轉換成任何物件指標,所以你通常會寫 int *p = malloc(n * sizeof *p);,這是一個常見又穩健的慣用法,依照指標所指之物的大小來決定區塊尺寸。
char *buf = malloc(1024); /* 容納 1024 個位元組 */ if (buf == NULL) return -1; /* 必須檢查 */ buf[0] = 'H'; /* 先寫再讀 */ /* ... */ free(buf); /* 把債還清 */
請求、檢查 NULL、先寫再讀(記憶體未初始化),最後剛好釋放一次。
malloc 給你的是未初始化的記憶體;若需要清零,請用 calloc 或事後呼叫 memset。把 malloc 的結果當成已清零來用,是垃圾值的常見來源。