iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 9
0
自我挑戰組

30 Days 如何把 C 語言偽裝成高階語言 OWO /系列 第 9

Days 9: 動態記憶體分配:malloc()、calloc()、realloc()、free(),內存洩露

▌動態記憶體分配


有關動態記憶體分配,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


上一篇
Days 8: 重溫指標:雜項:指標宣告、運算符
下一篇
Days 10: atexit()、函數程序結束時調用函數
系列文
30 Days 如何把 C 語言偽裝成高階語言 OWO /31

尚未有邦友留言

立即登入留言