周立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》,書本內(nèi)容公開后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。經(jīng)周立功教授授權(quán),本公眾號特對本書內(nèi)容進(jìn)行連載,愿共勉之。
第一章為程序設(shè)計(jì)基礎(chǔ),本文為1.9.3 free()函數(shù)和1.9.4 realloc()函數(shù)。
>>>>1.9.3free()函數(shù)
對于程序而言,不可再訪問的內(nèi)存塊被稱為垃圾,留有垃圾的程序存在內(nèi)存泄漏現(xiàn)象。雖然一些語言提供了垃圾收集器用于垃圾的自動定位和回收,但C語言不提供。要求每個(gè)程序負(fù)責(zé)回收各自的垃圾,方法是調(diào)用free()函數(shù)釋放不需要的內(nèi)存。
通常malloc()要與free()配套使用,當(dāng)動態(tài)內(nèi)存使用完畢時(shí),如果不及時(shí)釋放的話,必然導(dǎo)致“內(nèi)存泄露(即內(nèi)存空間減少)”,進(jìn)而影響程序的正常運(yùn)行。釋放內(nèi)存的free()函數(shù)原型如下:
void free(void *pointer);
即將malloc()返回的指針pointer作為參數(shù)傳給free()釋放內(nèi)存。雖然free()函數(shù)允許收回不再需要的內(nèi)存,但使用此函數(shù)會導(dǎo)致一個(gè)新的問題:懸空指針。雖然調(diào)用free(pi)函數(shù)會釋放pi,但不會改變pi本身。如果忘記了pi不再指向有效內(nèi)存塊,那么混亂就有可能隨即而來:
char *pi = malloc(5);
free(pi);
strcpy(pi, "abc");// 錯(cuò)誤
即修改了pi指向的內(nèi)存是嚴(yán)重的錯(cuò)誤,因?yàn)槌绦驅(qū)Υ藘?nèi)存失去了控制權(quán)。事實(shí)上,懸空指針是很難發(fā)現(xiàn)的,因?yàn)閹讉€(gè)指針可能指向相同的內(nèi)存塊,在釋放內(nèi)存塊后,全部的指針都懸空了。有了free()函數(shù),也可以用malloc()在運(yùn)行時(shí)分配一塊連續(xù)的內(nèi)存空間,達(dá)到改變數(shù)組大小的目的。比如:
char * pi = malloc(5);
即變量pi指向已經(jīng)在堆內(nèi)分配的5個(gè)連續(xù)字節(jié),好像聲明了一個(gè)有5個(gè)字符的數(shù)組一樣,顯然動態(tài)數(shù)組就是分配在“堆”上,用指針變量引用的數(shù)組。分配動態(tài)數(shù)組的步驟如下:
● 聲明一個(gè)指針變量用于保存數(shù)組變量首元素的地址;
●調(diào)用malloc()為數(shù)組變量中的元素分配內(nèi)存
●將malloc()的結(jié)果賦給指針變量。
由于不同的數(shù)據(jù)類型占用的內(nèi)存大小不一樣,其大小為數(shù)組變量元素個(gè)數(shù)乘以每個(gè)元素所占內(nèi)存的大小。比如,有5個(gè)int型元素的數(shù)組變量需要分配內(nèi)存。比如:
int *pi = malloc(5 * sizeof(int));
和數(shù)組不同的是,當(dāng)不再使用時(shí),必須釋放內(nèi)存。比如:
free(pi);
如果需要10個(gè)元素才夠用,那么應(yīng)該先釋放原內(nèi)存,然后再申請新內(nèi)存。比如:
free(pi);
pi = malloc(10 * sizeof(int));
顯然,存放在原內(nèi)存的數(shù)據(jù)不見了,為了保留原來的數(shù)據(jù),需要再做些工作:
int *temp = pi; //讓temp指向原內(nèi)存
pi = malloc(10 * sizeof(int)); //讓pi指向新內(nèi)存
memcpy(pi, temp, 5 * sizeof(int));//將原內(nèi)存的數(shù)據(jù)拷貝到新內(nèi)存
free(temp); //釋放原內(nèi)存
但上面的工作僅需一條語句即可完成,比如:
pi = realloc(pi, 10*sizeof(int));
由于free函數(shù)不會檢查傳入的指針是否為NULL,也不會在返回前將指針設(shè)置為NULL,因此程序員會創(chuàng)建自己的free函數(shù),saferfree函數(shù)的接口和實(shí)現(xiàn)詳見程序清單 1.49和程序清單 1.50。
程序清單1.49saferfree()函數(shù)的接口(saferFree.h)
1 #pragma once
2 void saferFree(void **pp);
程序清單1.50saferfreeh函數(shù)接口的實(shí)現(xiàn)(saferFree.c)
1 #include
2 #include
3
4 void saferFree(void **pp)
5 {
6 if(pp != NULL && *pp != NULL)
7 free(*pp);
8 *pp = NULL;
9 }
10 }
如果使用saferFree宏調(diào)用saferFree函數(shù),則可以省略類型轉(zhuǎn)換和傳遞指針的地址。即:
#define NewSaferFree(P) saferFree((void **)&p)
其調(diào)用形式如下:
int *pi = malloc(sizeof(int));
NewSaferFree(pi);
>>>1.9.4realloc()函數(shù)
alloc是allocate分配的縮寫,前綴re就是重新分配的意思。如果原內(nèi)存后面還有剩余的話,realloc()只是修改分配表,還是返回原內(nèi)存的地址;如果沒有剩余內(nèi)存的話,realloc()將申請新的內(nèi)存,然后將原內(nèi)存的數(shù)據(jù)拷貝到新內(nèi)存中,原內(nèi)存將被free()釋放掉,realloc()返回新內(nèi)存的地址。realloc()函數(shù)原型如下:
void *realloc(void *pointer, unsigned int size);
當(dāng)調(diào)用realloc()函數(shù)時(shí),point必須指向先前通過malloc、calloc或realloc的調(diào)用獲得的內(nèi)存塊。size表示新分配內(nèi)存的大小,以字節(jié)為單位。其作用是將pointer所指向的動態(tài)空間的大小改變?yōu)閟ize,pointer的值不變。如果重新分配不成功,則返回NULL;如果通過malloc()已經(jīng)獲得了動態(tài)空間,又不想改變其大小,則可以使用realloc()重新分配。
-
數(shù)據(jù)結(jié)構(gòu)
+關(guān)注
關(guān)注
3文章
569瀏覽量
40072 -
周立功
+關(guān)注
關(guān)注
38文章
130瀏覽量
37556
原文標(biāo)題:周立功:動態(tài)分布內(nèi)存——free()函數(shù)與realloc()函數(shù)
文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論