1. 程式人生 > >總算搞懂realloc

總算搞懂realloc

今天做資料結構的實驗,又第n次用到realloc。可惜我也第n次感到迷惑

最初接觸realloc時,是學線性表的時候。

書中寫的“在順序線性表L中第i個位置之前插入新的元素 e”

裡面有句話我實在不懂

if(L.length >= L.lisesize)
{
	newbase = (ElemType *)realloc(L.elem,(L.lisesize + LISTINCREMENT) * siezeof (ElemType));
	if(!newbase) exit(OVERFLOW);
	L.elem = newbase;
	L.listsize += LISTINCREMENT;
}

當時想,為什麼要先用 newbase 指向擴大後的記憶體,然後在判斷是否成功後,又令 L.elem 指向 newbase 所指向的記憶體,而不是直接
L.elem = (ElemType *)realloc(L.elem,(L.lisesize + LISTINCREMENT) * siezeof (ElemType));

狠狠的查了一堆文章才知道 realloc 的用法原來如此的不簡單。

首先第一種情況是,如果當前有連續的記憶體塊足夠分配的話,就直接講 L.elem 指向的記憶體空間擴大,使 L.elem 指向新的記憶體地址,並且返回 L.elem 。在這種情況下,newbase 與 L.elem 所指向的地址是一樣的。

但是第二種情況就不一樣了。如果當前沒有足夠的連續記憶體塊用來分配,那就要找到第一個足夠大的地方用來作新的記憶體,並令 newbase 指向它, 然後再將 L.elem 指向的內容複製到 newbase ,free 舊的記憶體,返回 newbase 。 這樣也就發生資料移動了。此時的 newbase 與L.elem 所指向的地址是不一樣的。

因此有時候也可以合理利用 newbase 與 L.elem 的相同與否來進行一些操作。

看回令我感到疑惑的問題,現在看來,這是不嚴謹的寫法。如果資料發生了移動,又令 L.elem 立即指向新的記憶體地址,這麼一來 realloc 就無法根據 L.elem 找回原先的記憶體塊,也因此無法 free 舊的記憶體了,即舊的記憶體的地址丟失,發生記憶體洩露。

嗯,基本上算是搞懂了。