認識C語言的動態內存分配

1. 引言

    數組是存儲在連續內存位置的項的集合,在實際使用中,往往需要增加或減少數組長度,這種情況下出現了動態內存分配(Dynamic Memory Allocation)。在程序運行時,改變數據結構(例如數組)大小的過程就被定義爲C語言的動態內存分配。在 /usr/include/stdlib.h 頭文件中,C定義了4個函數,以方便C編程中的動態內存分配,它們是malloc()、calloc()、realloc()和free(),分別用於分配、重新分配和釋放內存。

2. 動態內存分配

2.1 malloc()和calloc()的使用方法

    malloc(memory allocation的縮寫)方法用於動態分配具有指定大小的單個大塊內存。它返回void類型的指針,其指針類型可以靈活轉換,同時使用默認garbage value(內存中存儲的隨機值)初始化內存塊。其語法格式爲:
    ptr = (指針轉換格式*) malloc(分配的字節數)
    例如:

ptr = (int*) malloc(100 * sizeof(int));

    一般情況下int佔用4字節,整個語句會分配400字節的內存,指針ptr以int形式存儲首字節的地址。如果空間不足,則分配失敗並返回空(NULL)指針。示例:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    int i=0,num;
    printf("Please input the number of memory, the suggest range is [0,256]: ");
    scanf("%d",&num);
    int * ptr;
    ptr=(int *)malloc(num * sizeof(int));

    if ( ptr == NULL )
    {
        printf("Your input number is out of range.\n");
        exit(66);
    }
    else
    {
        while(i<num)
        {
            printf("ptr[%d] = %d, ptr address is %p\n", i, ptr[i], ptr+i);
            i++;
        }
    }
    free(ptr);
}

    正常情況下打印分配的內存內容及地址:

Please input the number of memory, the suggest range is [0,256]: 2
ptr[0] = 0, ptr address is 0x16eb010
ptr[1] = 0, ptr address is 0x16eb014

    如果需要分配的內存過大,返回空指針:

Please input the number of memory, the suggest range is [0,256]: 999999999
Your input number is out of range.

    calloc(continuous allocation的縮寫)方法與malloc()類似,用於動態分配指定類型的指定數量的內存塊。它用默認值“0”初始化每個塊。語法格式爲:

ptr = (指針轉換格式*)calloc(元素總數, 單一元素所佔字節數);
2.2 malloc()和calloc()的區別

    程序將它的可用內存分爲3部分來存儲變量:存儲靜態變量的靜態存儲區、存儲自動變量的棧、存儲動態分配變量的堆。靜態變量的生命週期貫穿程序始終;自動變量位於函數代碼塊中,隨着函數的逐層調用開始佔用內存,隨着函數調用結束反向釋放內存,符合棧後進先出的特點;動態分配變量的特點是可以在一個函數中創建內存塊,在其他函數中釋放,存取靈活的同時會造成內存使用的碎片化,所以動態內存往往導致進程比使用棧內存慢。
在這裏插入圖片描述
    malloc()和calloc()是動態分配內存的庫函數,這意味着在程序執行時從堆(heap)中分配內存。它們的區別不大:

  • 初始化:malloc()不初始化分配的內存,如果在初始化內存之前訪問內存內容,可能會得到 segmentation fault error 或是 garbage value;calloc()分配內存並將內存塊初始化爲0。
  • 當malloc()分配單一元素的內存大小時,配合memset()函數實現與calloc()相同的功能。
ptr = malloc(size); 
memset(ptr, 0, size);

    一般使用malloc()而不是calloc(),因爲malloc()比calloc()快,除非需要將內存初始化爲0。如果需要複製內存,malloc將是一個更好的選擇。

2.3 free()和realloc()

    free()方法用於動態地取消分配內存。使用函數malloc(和calloc()分配的內存不會自行釋放分配。因此,每當動態內存分配發生時,都會通過free()方法釋放內存來減少內存的浪費。語法爲:

free(ptr);

    realloc(reallocation)方法用於動態更改以前分配的內存大小。換言之,如果先前藉助malloc或calloc分配的內存不足,則可以使用realloc動態擴大變量佔用的內存。原有內存塊將保持現有值,新塊將使用默認garbage value初始化。語法爲:

ptr = realloc(ptr, newSize);

where ptr is reallocated with new size 'newSize'.

參考文獻

[1] RishabhPrabhu.Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()[EB/OL].https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/,2020-01-01.
[2] chakradharkandula, shubham_singh, Navfal, HarshitHiremath.Difference Between malloc() and calloc() with Examples[EB/OL].https://www.geeksforgeeks.org/difference-between-malloc-and-calloc-with-examples/,2020-01-01.
[3] ElementLS.堆棧的知識[EB/OL].https://zhuanlan.zhihu.com/p/34681978,2018-03-21.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章