在c裡,記憶體管理是通過專門的函式來實現。另外,為了相容各種程式語言,作業系統提供的介面通常是c 語言寫成的函式宣告(windows 本身也由c和組合語言寫成)。
1分配記憶體malloc函式
需要包含標頭檔案:
#include
函式宣告(函式原型)
void *malloc(int size);
說明:malloc 向系統申請分配指定size個位元組的記憶體空間。返回型別是void* 型別。void* 表示未確定型別的指標。c,c++規定,void* 型別可以強制轉換為任何其它型別的指標。
從函式宣告上可以看出。malloc 和new 至少有兩個不同:new
返回指定型別的指標,並且可以自動計算所需要大小。比如:
int *p;
p = new int; //返回型別為int* 型別(整數型指標),分配大小為sizeof(int);
或: int* parr;
parr = new int [100]; //返回型別為int* 型別(整數型指標),分配大小為sizeof(int) * 100;
而malloc則必須由我們計算要位元組數,並且在返回後強行轉換為實際型別的指標。
int* p;
p = (int *) malloc (sizeof(int));
第一、malloc 函式返回的是void * 型別,如果你寫成:p = malloc (sizeof(int)); 則程式無法通過編譯,報錯:「不能將void* 賦值給int * 型別變數」。所以必須通過(int *) 來將強制轉換。
第二、函式的實參為sizeof(int) ,用於指明乙個整型資料需要的大小。如果你寫成:
int* p = (int *) malloc (1);
**也能通過編譯,但事實上只分配了1個位元組大小的記憶體空間,當你往裡頭存入乙個整數,就會有3個位元組無家可歸,而直接「住進鄰居家」!造成的結果是後面的記憶體中原有資料內容全部被清空。
malloc 也可以達到new 的效果,申請出一段連續的記憶體,方法無非是指定你所需要記憶體大小。
比如想分配100個int型別的空間:
int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100個整數的記憶體空間。
另外有一點不能直接看出的區別是,malloc 只管分配記憶體,並不能對所得的記憶體進行初始化,所以得到的一片新記憶體中,其值將是隨機的。
除了分配及最後釋放的方法不一樣以外,通過malloc或new得到指標,在其它操作上保持一致。
2釋放記憶體free函式
需要包含標頭檔案(和malloc 一樣):
函式宣告:
void free(void *block);
即:void free(指標變數);
之所以把形參中的指標宣告為void* ,是因為free必須可以釋放任意型別的指標,而任意型別的指標都可以轉換為void *。
舉例:
int* p = (int *) malloc(4);
*p = 100;
free(p); //釋放p 所指的記憶體空間
或者:int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100個整數的記憶體空間。
……free(p);
free不管你的指標指向多大的空間,均可以正確地進行釋放,這一點釋放比delete/delete 要方便。不過,必須注意,如果你在分配指標時,用的是new或new,那麼抱歉,當你在釋放記憶體時,你並不能圖方便而使用free來釋放。反過來,你用malloc 分配的記憶體,也不能用delete/delete 來釋放。一句話,new/delete、new/delete、malloc/free三對均需配套使用,不可混用!
3.calloc()和realloc()
calloc()函式有兩個引數,分別為元素的數目和每個元素的大小,這兩個引數的乘積就是要分配的記憶體空間的大小:void *calloc(size_t numelements,size_t sizeofelement); 。
如果呼叫成功,函式malloc()和函式calloc()都將返回所分配的記憶體空間的首位址。函式malloc()和函式calloc()的主要區別是前者不能初始化所分配的記憶體空間,而後者能。如果由malloc()函式分配的記憶體空間原來沒有被使用過,則其中的每一位可能都是0;反之,如果這部分記憶體曾經被分配過,則其中可能遺留有各種各樣的資料。也就是說,使用malloc()函式的程式開始時(記憶體空間還沒有被重新分配)能正常進行,但經過一段時間(記憶體空間還已經被重新分配)可能會出現問題。
函式calloc()會將所分配的記憶體空間中的每一位都初始化為零,
也就是說,如果你是為字元型別或整數型別的元素分配記憶體,那麼這些元素將保證會被初始化為0;如果你是為指標型別的元素分配記憶體,那麼這些元素通常會被初始化為空指標;如果你為實型資料分配記憶體,則這些元素會被初始化為浮點型的零。
realloc()
原型:extern void *realloc(void *mem_address, unsigned int newsize);
用法:#include 有些編譯器需要#include
功能:改變mem_address所指記憶體區域的大小為newsize長度。
說明:如果重新分配成功則返回指向被分配記憶體的指標,否則返回空指標null。
當記憶體不再使用時,應使用free()函式將記憶體塊釋放。
注意:這裡原始記憶體中的資料還是保持不變的。
舉例:// realloc.c
#include
#include
main()
詳細說明及注意要點:
1、如果有足夠空間用於擴大mem_address指向的記憶體塊,則分配額外記憶體,並返回mem_address
這裡說的是「擴大」,我們知道,realloc是從堆上分配記憶體的,當擴大一塊記憶體空間時,realloc()試圖直接從堆上現存的資料後面的那些位元組中獲得附加的位元組,如果能夠滿足,自然天下太平。也就是說,如果原先的記憶體大小後面還有足夠的空閒空間用來分配,加上原來的空間大小=newsize。那麼就ok。得到的是一塊連續的記憶體。
2、如果原先的記憶體大小後面沒有足夠的空閒空間用來分配,那麼從堆中另外找一塊newsize大小的記憶體,並把原來大小記憶體空間中的內容複製到newsize中,返回新的mem_address指標(資料被移動了),老塊被放回堆上。
例如:#include
char *p,*q;
p = (char * ) malloc (10);
q=p;
p = (char * ) realloc (p,20);
…………………………
這段程式也許在編譯器中沒有辦法通過,因為編譯器可能會為我們消除一些隱患!在這裡我們只是增加了乙個記錄原來記憶體位址的指標q,然後記錄了原來的記憶體位址p,如果不幸的話,資料發生了移動,那麼所記錄的原來的記憶體位址q所指向的記憶體空間實際上已經放回到堆上了!這樣一來,我們應該終於意識到問題的所在和可怕了吧!
3、返回情況
返回的是乙個void型別的指標,呼叫成功。(這就再你需要的時候進行強制型別轉換)
返回null,當需要擴充套件的大小(第二個引數)為0並且第乙個引數不為null,此時原記憶體變成了「freed(游離)」的了。
返回null,當沒有足夠的空間可供擴充套件的時候,此時,原記憶體空間的大小維持不變。
4、特殊情況
如果mem_address為null,則realloc()和malloc()類似。分配乙個newsize的記憶體塊,返回乙個指向該記憶體塊的指標。
如果newsize大小為0,那麼釋放mem_address指向的記憶體,並返回null。
如果沒有足夠可用的記憶體用來完成重新分配(擴大原來的記憶體塊或者分配新的記憶體塊),則返回null.而原來的記憶體塊保持不變。
malloc函式和free函式
c語言中的動態記憶體分配函式malloc和free使用起來很靈活,但是也很容易導致錯誤,如果知道了malloc和free的實現原理,那麼,出錯的機會就很小了。malloc的實現原理 作業系統維護了乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶。呼叫malloc函式時,作業系統沿鍊錶尋找乙個大...
free函式和malloc函式
初學c和資料結構是對其很不明確,通過一些資料,稍微理解了,所以記下以後複習之用,如果有錯誤或者理解不當的情況請指正,不勝感激。一malloc和free函式 malloc函式 void malloc sizeof byte 向系統申請大小的空間,然後返回指向這個記憶體的指標。如果記憶體分配失敗,則返回...
malloc與free和new delete的區別
不同點 1 操作物件有所不同。malloc與free是c c 語言的標準庫函式,new delete 是c 的運算子。對於非內部資料類的物件而言,光用maloc free 無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件消亡之前要自動執行析構函式。由於malloc free 是庫函式...