爲準確瞭解free函數,讓我們看看malloc申請動態內存和free函數被調用時,內存做了哪些工作:
int main()
{
int *arr=(int*)malloc(10*sizeof(int));
arr[0] = 100;
arr[1] = 200;
free(arr);
arr = NULL;
char src[]={"shit man"};
char *str = (char*)malloc(10);
strcpy(str,src);
free(str);
str = NULL;
return 0;
}
申請40個字節的內存塊大小爲28,在被申請內存塊首地址的16字節之前被寫入;
調用free函數後,之前申請的內存塊被覆蓋;
接着申請10個字節大小的內存塊,轉成16進製爲0a,在內存塊首地址的16字節之前被寫入到內存裏;
使用free函數釋放內存時,函數在內存塊首地址之前16個字節處找到內存塊的大小。
因此若被free的爲一個空指針是沒有任何意義的,編譯器也不會報錯。
申請字符串函數,初始化遇到問題
char* ArrChar()
{
char *arr = (char*)malloc(10*sizeof(char));
return arr;
}
int main()
{
char *p=ArrChar();
free(p);
return 0;
}
由於未初始化的指針自動初始化爲0xcccccccc或0xcdcdcdcd,而不是取隨機值,使用strcpy函數,可以進行正確的初始化。
如果內存不夠的情況,函數庫爲我們提供了另一個函數realloc,
int main()
{
int *p = (int*)malloc(10*sizeof(int));
for(int i=0; i<10; i++)
{
p[i]=i;
}
int tmp = 0;
p = (int*)realloc(p,100*sizeof(int));
for(int i=0; i<20; i++)
{
p[i]=i;
}
tmp = 1;
p = (int*)realloc(p,5*sizeof(int));
for(int i=0; i<5; i++)
{
p[i]=i;
}
return 0;
}
監視p 的地址爲
動態申請長度爲40字節的內存
使用realloc函數,得到長度爲400字節的內存,p的地址仍爲
調用realloc函數,得到新的長度爲20字節的內存,p的地址爲
本次測試realloc函數申請更大或更小內存,指針的位置均爲發生改變,原來的內存已經被覆蓋。
參考文獻:
free函數是如何確定要釋放多少內存空間的