當乙個陣列被宣告時,它所需要的內存在編譯時就被分配。但是也可以通過使用動態記憶體分配在執行時為它分配記憶體。
一、為什麼要使用動態記憶體分配?
在宣告陣列的時候,必須用乙個編譯時常量指定陣列長度,但實際上,陣列的長度常常在執行時才知道,這是由於它所需要的記憶體空間取決於輸入資料。所以,有時候,我們開闢的空間可能不夠用,這個時候,往往使用動態記憶體分配。
二、malloc和free以及calloc和realloc
工作大致過程:這兩個函式維護乙個可用記憶體池。當乙個程式另外需要一些記憶體時,它就呼叫malloc,malloc從記憶體池中提取一塊適合的記憶體,並向該程式返回乙個指向這塊記憶體的指標。這塊記憶體並沒有以任何方式進行初始化。但是初始化非常重要,所以程式設計師來動手初始化(也可以使用calloc函式)。當一塊以前分配的記憶體不再使用時,程式呼叫free函式把它歸還給記憶體池供以後之需。void *malloc(size_t size);
void
free(void *pointer);
注意:對每個從malloc返回的指標都進行null檢查是非常重要的。因為當記憶體池是空的或者無法滿足需要的時候,malloc一般會向作業系統請求得到更多的記憶體,並在這塊新記憶體上執行分配任務。如果作業系統無法向malloc提供更多記憶體,malloc就會返回null指標。
從函式中表示式中,我們可以看出malloc返回的是乙個void*指標,所以有時候我們需要型別轉換。
malloc和calloc的區別:void *calloc(size_t num_elements,size_t element_size);
void realloc(void *ptr,size_t new_size);
calloc在返回指向記憶體的指標之前會把它初始化。calloc的引數包括所需元素的數量和每個元素的位元組數。根據這些值,它能夠計算出總共需要分配的記憶體。
realloc用於修改乙個原先已經分配好的記憶體塊的大小。可以增或刪。
舉個小例子:
三、常見錯誤int
*pi;
pi = malloc(25
*sizeof(int));
int*pi2,i;
pi2 = pi;
for(i = 0; i< 25;i++)
/*初始化陣列為0
*/*pi2++ = 0; //pi[i] = 0;
對null指標進行解引用操作、對分配的記憶體進行操作時越過邊界、釋放並非動態分配的記憶體、試圖釋放一塊動態分配的記憶體的一部分以及一塊動態記憶體被釋放之後被繼續使用等。
warning:
動態記憶體分配最常見的錯誤就是忘記檢查所請求的記憶體是否成功分配,malloc巨集接受元素的數目能及每種元素的型別,計算總共需要的記憶體位元組數,並呼叫alloc獲得記憶體。alloc呼叫malloc並進行檢查,確保返回的指標不是null。
**如下:
記憶體洩露:申請的記憶體用完了卻不釋放,將會引起記憶體洩漏。記憶體洩露會榨幹作業系統的記憶體,直到整個程式無法工作,甚至會引起其他工作的丟失。是非常危險的。/*定義個不易發生錯誤的記憶體分配器alloc.h*/
#include
#define malloc //不要直接使用malloc
/*用於防止由於其他**塊直接塞入程式而導致的偶爾直接呼叫malloc的行為,增加這個指令以後,如果程式偶爾呼叫了malloc,程式將由於語法錯誤而無法編譯,在alloc中必須加入#undef指令,這樣才能呼叫malloc而不至於出錯。
*/#define malloc(num,type)(type*)alloc((num)*sizeof(type))
extren void *alloc(size_t size);
/*不易發生錯誤的記憶體分配器的實現alloc.c*/
#include
#include "alloc.h"
#undef malloc
void *alloc(size_t size)
return new_mem;
}/*乙個使用很少引起錯誤的記憶體分配器的程式a_client.c*/
#include "alloc.h"
void function()
四、程式分析
以下給出乙個使用malloc的例子:
input:1 5 3 4 2#include
#include
#include
#include
#define malloc
#define malloc(num,type) (type *)alloc((num) * sizeof(type))
extern
void *alloc(size_t size);
#undef malloc
void *alloc(size_t size)
return new_mem;
}int compare_integers(void
const* a,void
const* b)
int main()
array = malloc(n_values,int);
/*array = malloc(n_values * sizeof(int));
if(array == null)*/
printf("輸入:\n");
for(i = 0;i < n_values;i++)
}qsort(array,n_values,sizeof(int),compare_integers);
printf("結果為:\n");
for(i = 0;i < n_values; i++)
printf("%d ",array[i]);
printf("\n");
free(array);
return exit_success;
}
output:1 2 3 4 5
動態記憶體分配
在c 中建立乙個物件時,我們必須要為這個物件申請一塊記憶體,而且要用建構函式對這塊記憶體進行初始化。c 中的new和delete相對於c的庫函式malloc和free在這方面有很大的優勢,所以我們主要講的是運算子new和delete。當用new來建立乙個物件時,它會自動在堆裡為物件分配記憶體並且為這...
動態記憶體分配
為什麼使用動態記憶體分配?c語言中的一切操作都是基於記憶體的 變數和陣列都是記憶體的別名,如何分配這些記憶體由編譯器在編譯期間決定 定義陣列的時候必須指定陣列唱的 而陣列長度是在編譯期就必須決定的 需求 程式執行的過程中,可能需要使用一些額外的記憶體空間 malloc和free malloc和fre...
動態記憶體分配
c的儲存類別有4種 自動的 auto 靜態的 statics 暫存器的 register 外部的 extern 全域性變數時分配在記憶體中的靜態儲存區 靜態區域性變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元,是在編譯時賦初值的,只賦初值一次,在程式執行時它已有初值,以後每次呼叫函式時不再重新賦初...