▌動態記憶體分配


有關動態記憶體分配,C 會用 malloc()、calloc()、realloc()、free() 這四個函數,
網上資料很多,我簡略說一下就算了。
唯一需要留意的是 realloc() 的行為。

▌如何分配空間:


void *malloc(size_t size):

輸入:字節數
回傳:已分配空間的地址,失敗返回 NULL 。
如果 size = 0 ,也會回傳一個合法的指標。

void *calloc(size_t nitems, size_t size):

輸入:要分配的元素數目、每一格元素的字節數
回傳:已分配空間的地址,失敗返回 NULL 。
同時把所有空間的數值初始化為 0 。

▌如何釋放空間:

void free(void *ptr):

輸入:地址
釋放從該地址分配的空間。 (哪裏分配哪裏釋放)
沒有回傳。

▌如何改變已經分配的空間大小:

void *realloc(void *ptr, size_t size):

輸入:曾經分配過空間的地址、新的字節數
回傳:新已分配空間的地址,失敗返回 NULL 。
如果 ptr = NULL ,
等價呼叫 malloc(size) 。
如果 size = 0 ,
等價呼叫 free(ptr) 。
// malloc 會回傳一個合法的指標,這個不會。

▌注意一下, realloc() 有一些特殊的行為:

如果原空間其後的連續記憶體足夠,
擴大原本的空間,
回傳 原空間的地址
如果其後的連續記憶體不足
會尋找新的、足夠長的記憶體空間,
把原本空間的數據複製至新空間,
釋放 原空間,
回傳 新空間的地址

▌使用 realloc 時不應該:

ptr = realloc(ptr, new_size);
如果分配失敗,會造成內存洩漏
所有應該找一個暫存指標:
new_ptr = realloc(ptr, new_size);
if(new_ptr == null){  //用 !new_ptr 檢查也可以
    // 錯誤處理
}
ptr = new_ptr

▌內存洩露的問題:

使用 C/C++ ,需要自行管理記憶體空間,
存在著讓人痛心的內存洩露的問題。
來個最無聊的例子:
malloc(1000);
回傳的地址沒有接收,直接內存洩露。
這也是 Day 4 中提到不希望用回傳地址方式的原因。
其實沒有人這麼笨...,可以不用擔心。
不用回傳地址方式其實會變麻煩了,可能需要額外傳入一個類型參數。
為什麼我還要這樣做呢?
這關係到例外處理的實現,到時候再說。OWO

除了沒有接收,直接內存洩露之外,
最常見的就是忘記釋放已分配的空間
即是 有 malloc() 沒有 free()。
這正是垃圾回收要處理的事。

還有 atexit() 函數要介紹,
就要開始實現垃圾回收的部分了,第九天而已啊。ಠ_ಠ
有點擔心能不能撐下30天。 ( ˘•ω•˘ ) 應該可以的吧ww。

▌參考資料:

C動態記憶體分配 - 維基百科,自由的百科全書
https://zh.wikipedia.org/wiki/C%E5%8A%A8%E6%80%81%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D
malloc() - C語言庫函數 - C語言標準庫
http://tw.gitbook.net/c_standard_library/c_function_malloc.html
calloc() - C語言庫函數 - C語言標準庫
http://tw.gitbook.net/c_standard_library/c_function_calloc.html
realloc() - C語言庫函數 - C語言標準庫
http://tw.gitbook.net/c_standard_library/c_function_realloc.html
free() - C語言庫函數 - C語言標準庫
http://tw.gitbook.net/c_standard_library/c_function_free.html
安全起见,小心使用C语言realloc()函数_C语言中文网
http://c.biancheng.net/cpp/html/2536.html
realloc 用法 - snlying的专栏 - CSDN博客
https://blog.csdn.net/snlying/article/details/4005238