文章目錄
- 前言
- 一、動態記憶體開辟函式
- 1. malloc
- 2.free
- 3.calloc
- 4.realloc
- 二、常見動態記憶體錯誤
- 1.對NULL的解參考操作
- 2.對動態開辟的空間越界訪問
- 3.對非動態開辟記憶體使用free釋放
- 4.使用free釋放一塊動態開辟記憶體的一部分
- 5.對同一塊動態記憶體多次釋放
- 6.忘記釋放動態開辟的記憶體
- 感謝閱讀,如有錯誤請批評指正
前言
為什么會存在動態記憶體分配呢?
非動態的記憶體開辟方式有兩種:
int i;//在堆疊上開辟四個位元組的空間
char arr[10];//在堆疊上開辟連續10個一個位元組的空間
但是上述開辟空間的方式有兩個特點:
(1)開辟空間的大小是固定的,
(2)陣列在宣告的時候,必須用常量指定陣列的長度而且之后無法修改,
但是對于空間的需求,不僅僅是上述的情況,有時候需要的空間大小可能是一個變數,那么使用陣列來開辟空間的方式就不能滿足需求了, 這時候就會用到動態記憶體開辟,
一、動態記憶體開辟函式
1. malloc
malloc的函式原型為
void* malloc (size_t size);
//傳入的引數為開辟的空間所占的位元組
這個函式會向記憶體申請一塊連續可用的空間,并回傳指向這塊空間的指標,注意這里的回傳型別為void*,所以在接收時需要進行強制型別轉換,
如果開辟成功,則回傳一個指向所開辟的空間的指標,
如果開辟失敗,則回傳一個NULL指標,因此malloc的回傳值一定要做檢查,
如果傳入的引數 size 為0,malloc的行為是標準未定義的,如何處理取決于編譯器,
代碼如下(示例):
int main()
{
int n;
scanf("%d", &n);
//強制型別轉換
int* p = (int*)malloc(sizeof(int)* n);
//動態開辟n個大小為int的空間
if (p == NULL)//檢查是否開辟成功
{
printf("開辟失敗\n");
return 0;
}
int i = 0;
for (i = 0; i < n; i++)
{
*(p + i) = i;
}
//將p后的n個空間置為0到n-1
free(p);//釋放空間
p = NULL;//將指標置為空
return 0;
}
2.free
free函式是專門從來做記憶體的釋放和回收的,函式原型如下:
void free (void* ptr);
free函式用來釋放動態開辟的記憶體,
如果引數 ptr 指向的空間不是動態開辟的,則free函式的行為是未定義的,
如果引數 ptr 是NULL指標,則什么事都不發生,
引數ptr被釋放后其所指向的空間不可使用,但由于ptr仍指向這一塊空間,所以建議在free后再將ptr置為NULL,
3.calloc
calloc也是用來動態開辟記憶體的函式,函式原型如下:
void* calloc (size_t num, size_t size);
calloc的功能是開辟num個大小為size個位元組的空間,并且把空間的每個位元組初始化為0,
注意這里的回傳型別為void*,所以在接收時需要進行強制型別轉換,
代碼如下(示例):
int main()
{
int* p = (int*)calloc(10, sizeof(int));
if (p == NULL)
{
printf("開辟失敗\n");
return 0;
}
free(p);
p = NULL;
return 0;
}

4.realloc
realloc函式的出現讓動態記憶體管理更加靈活,
有時會發現之前申請的空間太小了,有時候又會覺得之前申請的空間過大了,為了合理的使用記憶體,我們會對記憶體的大小做靈活的調整,realloc函式就可以做到對動態開辟記憶體大小的調整,
realloc函式原型如下:
void* realloc (void* ptr, size_t size);
ptr是指向要調整的記憶體地址的指標,size為調整之后新大小,回傳值為調整之后的記憶體起始位置,
注意這里的回傳型別為void*,所以在接收時需要進行強制型別轉換,
realloc函式調整原記憶體空間大小的基礎上,還會將原來記憶體中的資料移動到新的空間,
realloc在調整記憶體空間的時存在兩種情況:
(1)原有空間之后有足夠大的空間,則在原有記憶體之后直接追加空間,原來空間的資料不發生變化,
(2)原有空間之后沒有足夠多的空間,則擴展的方法是:在堆空間上另找一個合適大小的連續空間來使用,這時函式回傳的是一個新的記憶體地址,并自動把之前的空間釋放掉,
二、常見動態記憶體錯誤
1.對NULL的解參考操作
int* p = (int*)malloc(sizeof(int) * 10);
*p = 20;//如果開辟失敗,p是空指標
//對空指標進行解參考操作會出現問題
free(p);
2.對動態開辟的空間越界訪問
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
return 0;
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//當i為10的時候越界訪問
}
free(p);
3.對非動態開辟記憶體使用free釋放
int a = 10;
int *p = &a;
free(p);//free非動態開辟的記憶體會出現問題
4.使用free釋放一塊動態開辟記憶體的一部分
int *p = (int *)malloc(10*sizeof(int));
p++;
free(p);//此時的p指向動態開辟記憶體的下一個位置而不是起始
//free時會出現問題
5.對同一塊動態記憶體多次釋放
int *p = (int *)malloc(10*sizeof(int));
free(p);
free(p);//重復釋放同一塊記憶體空間會出現問題
6.忘記釋放動態開辟的記憶體
如果只向記憶體申請空間而不釋放,就會導致記憶體泄漏,動態開辟的記憶體一定要正確的釋放,
感謝閱讀,如有錯誤請批評指正
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/271608.html
標籤:其他
