動態記憶體分配
阿新 • • 發佈:2021-01-24
技術標籤:C語言
文章目錄
動態記憶體(堆區)分配的函式:
需帶標頭檔案#include<stdlib.h>
-
malloc(申請空間)
voidmalloc(size_t size)
這個函式向記憶體申請一塊連續可用的空間,並返回指向這塊空間的指標
如果開闢成功,則返回一個指向這塊空間的指標;如果開闢失敗,則返回一個NULL指標,因此malloc函式的返回值一定要做檢查
返回型別是void,所以malloc函式並不知道開闢空間的型別,具體由自己而定。 -
free
void* free(void* ptr)
釋放和回收所申請的空間
如果引數ptr是NULL指標,則函式什麼也不做
當申請的空間不再使用時一定要釋放
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main(){
int* p = (int*)malloc(5*sizeof(int));//開闢空間
int i=0;
if(p==NULL){//開闢失敗
printf("%s\n",strerror(errno)) ;//錯誤原因
}
else{//開闢成功
for(i=0;i<5;i++){
*(p+i)=i;
}
}
for(i=0;i<5;i++){
printf("%d ",*(p+i));
}
free(p);//釋放空間
p=NULL;//保險,定位空指標
return 0;
}
- calloc(與malloc相似,用完也要釋放)
void* calloc(size_t num,size_t size)
此函式也是為num個大小為size的元素開闢一塊空間,並把空間每個位元組初始化為0,比malloc的效率低。 - realloc(對函式記憶體進行調整)
ptr是要調整的記憶體地址,size是調整後記憶體的大小
返回值為記憶體的起始位置,還會將原資料移動到新的空間
使用realloc函式追加,注意事項:
1.如果p指向的空間後有足夠的空間可以追加,則直接追加後返回p
2.如果p指向的空間後沒有足夠的空間追加,則realloc函式會重新找一個新的記憶體區域,開闢一塊滿足需求的空間,並且把原來記憶體裡的資料拷貝回來,釋放舊的記憶體空間
3.得用一個新的變數來接收realloc函式的返回值
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main(){
int* p = (int*)malloc(5*sizeof(int));
int i=0;
if(p==NULL){//開闢失敗
printf("%s\n",strerror(errno));
}
else{//開闢成功
for(i=0;i<5;i++){
*(p+i)=i;
}
}
//空間不夠了,要追加
int* pr=(int*)realloc(p,20*sizeof(int));//這塊也要判斷空間是否開闢成功
if(pr==NULL){
printf("%s\n",strerror(errno));//打印出錯誤的原因
}
else{
int j=0;
for(j=i;j<20;j++){
*(pr+j)=j;
}
for(i=0;i<20;i++){
printf("%d ",*(pr+i));
}
}
free(pr);
pr=NULL;
return 0;
}
realloc函式常見的引用錯誤:
1.沒有對realloc函式開闢的空間進行判斷,導致對NULL進行解引用
2.對動態開闢的記憶體進行越界訪問
3.對非動態開闢的空間進行釋放
4.使用free釋放動態開闢記憶體的一部分
eg:
int* p=(int*)mallloc(40);
if(p == NULL){
return 0;
}
else{
int i=0;
for(i=0;i<10;i++){
*p++=i;#p被改變了,
}
}
free(p);//此處的P指向的是第十一個int型,只是釋放了部分
return 0;
}
5.對同一塊動態記憶體的多次釋放
int* p=(int*)mallloc(40);
if(p==NULL){
return 0;
}
free( p );
p=NULL//可以進行避免
.....
free(p);
6.動態記憶體忘記釋放(記憶體洩漏)
while(1){
malloc(1);
}
如果只開闢空間不釋放空間,在迴圈結束之前已耗盡所有記憶體,這類問題被稱為記憶體洩漏。
柔性陣列
#include<stdio.h>
#include<stdlib.h>
struct s{
int n;
int arr[0];//未知大小——柔型陣列,陣列大小可以調整
};
int main(){
int i=0;
struct s*p=(struct s*)malloc(sizeof(struct s)+5*sizeof(int));
p->n=100;
for(i=0;i<5;i++){
p->arr[i]=i;
}
for(i=0;i<5;i++){
printf("%d ",p->arr[i]);
}
free(p);//釋放空間
p=NULL;
return 0;
}
下者(繁)同上者等價,結果相同:
#include<stdio.h>
#include<stdlib.h>
struct s{
int n;
int *arr;
};
int main(){
int i;
struct s*pr=(struct s*)malloc(sizeof(struct s));
pr->arr=(int *)malloc(5*sizeof(int));
for(i=0;i<5;i++){
pr->arr[i]=i;
}
for(i=0;i<5;i++){
printf("%d ",pr->arr[i]);
}
free(pr->arr);//先釋放結構體中的開闢的空間
pr->arr=NULL;
free(pr);//釋放空間
pr=NULL;
return 0;
}