今天做数据结构的实验,又第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 旧的内存了,即旧的内存的地址丢失,发生内存泄露。
嗯,基本上算是搞懂了。