1. 程式人生 > 其它 >動態記憶體分配

動態記憶體分配

技術標籤:C語言

文章目錄

動態記憶體(堆區)分配的函式:

需帶標頭檔案#include<stdlib.h>

  • malloc(申請空間)
    voidmalloc(size_t size)
    這個函式向記憶體申請一塊連續可用的空間,並返回指向這塊空間的指標
    如果開闢成功,則返回一個指向這塊空間的指標;如果開闢失敗,則返回一個NULL指標,因此malloc函式的返回值一定要做檢查
    返回型別是void
    ,所以malloc函式並不知道開闢空間的型別,具體由自己而定。

  • free
    void* free(void* ptr)
    釋放和回收所申請的空間

    如果引數ptr指向的空間不是動態開闢的,那free的行為是未定義的
    如果引數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(對函式記憶體進行調整)
    voidrealloc(voidptr,size_t size)
    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;
}