C—動態內存分配之malloc與realloc的區別


在程序的執行期間分配內存時,內存區域中的這個空間稱為堆(heap)。還有另一個內存區域,稱為棧(stack),其中的空間分配給函數的參數和本地變量。在執行完該函數后,存儲參數和本地變量的內存空間就會釋放。堆中的內存是由程序員控制的。在分配堆上的內存時,由程序員跟蹤所分配的內存何時不再需要,並釋放這些空間,以便於以后重用它們。

     使用動態內存很明顯的好處就是:不需要預先分配存儲空間且分配的空間可以根據程序的需要擴大或縮小,這樣可以有效的使用內存空間。

malloc和free

     C函數庫中的malloc和free分別用於執行動態內存分配和釋放。這兩個函數的原型如下所示,他們都在頭文件stdlib.h中聲明。

     void *malloc ( size_t size );

     void free ( void *pointer );

     malloc的作用是在內存的動態存儲區中分配一個長度為size的連續空間。其參數是一個無符號整形數,返回值是一個指向所分配的連續存儲域的起始地址的指針。還有一點必須注意的是,當函數未能成功分配存儲空間(如內存不足)就會返回一個NULL指針。所以在調用該函數時應該檢測返回值是否為NULL,確保非空之后再使用非常重要。malloc所分配的內存是一塊連續的空間。同時,malloc實際分配的內存空間可能會比你請求的多一點,但是這個行為只是由編譯器定義的。malloc不知道用戶所請求的內存需要存儲的數據類型,所以malloc返回一個void *的指針,它可以轉換為其它任何類型的指針。

     由於內存區域總是有限的,不能不限制地分配下去,而且一個程序要盡量節省資源,所以當所分配的內存區域不用時,就要釋放它,以便其它的變量或者程序使用。這時我們就要用到free函數。free的參數必須要么是NULL,要么是從malloc、relloc、calloc返回的值。作用是釋放之前返回的指針指向的內存空間,向free傳遞一個NULL參數不會產生任何效果。

calloc和realloc與malloc的區別

     calloc和realloc的原型如下:

     void *calloc ( size_t num_elements, size_t element_size );

     void *realloc (void *ptr, size_t new_size );

     calloc和malloc 主要的區別在於前者在返回內存的指針之前將它初始化為0,另外它們請求數量的方式不同。calloc的參數包括所需元素的數量和每個元素的字節,根據這些值可以計算出總共需要分配的內存空間。

     realloc函數用於修改一個原先已經分配的內存塊的大小,可以使一塊內存的擴大或縮小。當起始空間的地址為空,即*ptr = NULL,則同malloc。當*ptr非空:若nuw_size < size,即縮小*ptr所指向的內存空間,該內存塊尾部的部分內存被拿掉,剩余部分內存的原先內容依然保留;若nuw_size > size,即擴大*ptr所指向的內存空間,如果原先的內存尾部有足夠的擴大空間,則直接在原先的內存塊尾部新增內存,如果原先的內存尾部空間不足,或原先的內存塊無法改變大小,realloc將重新分配另一塊nuw_size大小的內存,並把原先那塊內存的內容復制到新的內存塊上。因此,使用realloc后就應該改用realloc返回的新指針。

使用方法程序示例

復制代碼
1 int *ptr =NULL;
2 ptr = (int*)malloc(sizeof(int)*size);
3 if (*ptr == NULL)
4 {
5     strerror(error);
6     return;
7 }
復制代碼

     上例中動態分配了size個整型存儲區域。動態分配內存的步驟可細分為:分配size個整型的連續存儲空間,並返回一個指向其起始地址的整型指針把此整型指針地址賦給ptr, 檢測返回值是否為NULL。注意,類型轉換(int*)將函數返回的地址轉換成int類型的指針。這么做是因為malloc()是一般用途的函數,可為任何類型的數據分配內存。sizeof是一個運算符,它返回一個size_t類型的無符號整數,該整數是存儲它的參數需要的字節數。它把關鍵字如int或float等作為參數,返回存儲該類型的數據項所需的字節數。它的參數也可以是變量或數組名。把數組名作為參數時,sizeof返回存儲整個數組所需的字節數。前一個例子請求分配足以存儲size個int數據項的內存。以這種方式使用sizeof,可以根據不同的C編譯器為int類型的值自動調整所需的內存空間。

1 int *p1,*p2; 
2  p1 = (int*)malloc(size * sizeof(int));
3  p2=p1; 
4 ……  
5 free(p1);  /*或者free(p2)*/

     給free函數傳遞其它的值很可能造成死機或其它災難性的后果。注意:這里重要的是指針的值,而不是用來申請動態內存的指針本身。

     malloc返回值賦給p1,又把p1的值賦給p2,所以此時p1,p2都可作為free函數的參數。malloc函數是對存儲區域進行分配的。 free函數是釋放已經不用的內存區域的。 所以由這兩個函數就可以實現對內存區域進行動態分配並進行簡單的管理了。

下面是使用動態分配的內存的基本規則:

●避免分配大量的小內存塊。分配堆上的內存有一些系統開銷,所以分配許多小的內存塊比分配幾個大內存塊的系統開銷大。

●僅在需要時分配內存。只要使用完堆上的內存塊,就釋放它。

●總是確保釋放已分配的內存。在編寫分配內存的代碼時,就要確定在代碼的什么地方釋放內存。

●在釋放內存之前,確保不會無意中覆蓋堆上分配的內存的地址,否則程序就會出現內存泄漏。在循環中分配內存時,要特別小心。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM