內存泄漏
使用 malloc()、calloc()、realloc() 動態分配的內存,如果沒有指針指向它,就無法進行任何操作,這段內存會一直被程序占用,直到程序運行結束由操作系統回收。
請看下面的代碼:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *p = (char*)malloc(100 * sizeof(char));
p = (char*)malloc(50 * sizeof(char));
free(p);
p = NULL;
return 0;
}
該程序中,第一次分配 100 字節的內存,並將 p 指向它;第二次分配 50 字節的內存,依然使用 p 指向它。
這就導致了一個問題,第一次分配的 100 字節的內存沒有指針指向它了,而且我們也不知道這塊內存的地址,所以就再也無法找回了,也沒法釋放了,這塊內存就成了垃圾內存,雖然毫無用處,但依然占用資源,唯一的辦法就是等程序運行結束后由操作系統回收。
這就是 內存泄露(Memory Leak),可以理解為程序和內存失去了聯系,再也無法對它進行任何操作。
內存泄漏形象的比喻是“操作系統可提供給所有程序使用的內存空間正在被某個程序榨干”,最終結果是程序運行時間越長,占用內存空間越來越多,最終用盡全部內存空間,整個系統崩潰。
再來看一種內存泄露的情況:
int *pOld = (int*) malloc( sizeof(int) );
int *pNew = (int*) malloc( sizeof(int) );
這兩段代碼分別創建了一塊內存,並且將內存的地址傳給了指針 pOld 和 pNew。此時指針 pOld 和 pNew 分別指向兩塊內存。
如果接下來進行這樣的操作:
pOld=pNew;
pOld 指針就指向了 pNew 指向的內存地址,這時候再進行釋放內存操作:
free(pOld);
此時釋放的 pOld 所指向的內存空間就是原來 pNew 指向的,於是這塊空間被釋放掉了。但是 pOld 原來指向的那塊內存空間還沒有被釋放,不過因為沒有指針指向這塊內存,所以這塊內存就造成了丟失。
另外,你不應該進行類似這面這樣的操作:
malloc( 100 * sizeof(int) );
這樣的操作沒有意義,因為沒有指針指向分配的內存,無法使用,而且無法通過 free() 釋放掉,造成了內存泄露。
最后的總結
1.free() 函數的用處在於實時地回收內存,如果程序很簡單,程序結束之前也不會使用過多的內存,不會降低系統的性能,那么也可以不用寫 free() 函數。當程序結束后,操作系統會釋放內存。
2.但是如果在開發大型程序時不寫 free() 函數,后果是很嚴重的。這是因為很可能在程序中要重復一萬次分配10MB的內存,如果每次進行分配內存后都使用 free() 函數去釋放用完的內存空間, 那么這個程序只需要使用10MB內存就可以運行。但是如果不使用 free() 函數,那么程序就要使用100GB 的內存!這其中包括絕大部分的虛擬內存,而由於虛擬內存的操作需要讀寫磁盤,因此,這樣會極大地影響到系統的性能,系統因此可能崩潰。
3.因此,在程序中使用 malloc() 分配內存時都對應地寫出一個 free() 函數是一個良好的編程習慣。這不但體現在處理大型程序時的必要性,並能在一定程度上體現程序優美的風格和健壯性。