C語言學習之動態內存管理

1、問什麼要動態內存管理?

在進行數據存儲的時候,我們經常的做法是利用數組開闢指定大小的空間用以存儲數據,但是數組的具體大小取決於輸入的數據,因此往往在程序運行時才知道所需數組的內存空間的大小。爲了達到對內存空間的合理使用,這就要就我們根據輸入數據的不同來開闢不同大小的內存空間,繼而出現動態內存分配。動態內存分配在程序運行時爲指定的變量分配內存,其分配的內存空間位於堆區。此外,在棧區可開闢的空間大小小於堆區,因此在需要開闢較大的內存空間時,也需要使用動態內存分配。

2、動態內存分配函數

 malloc、calloc、realloc之間的聯繫與區別:malloc、calloc函數均用於在堆區開闢指定大小的內存空間,但是malloc函數在開闢時,只是開闢指定大小的內存空間,不對開闢好的內部才能進行初始化操作,而callo函數在開闢空間的同時對該空間的內容初始化爲0,其返回值的類型均爲void *。realloc函數用來修改已經分配好內存空間的大小,其返回值也爲void*;realloc函數在調整內存空間時的兩種情況:①原有空間之後有足夠大小的空間:這種情況在進行內存擴增的時,直接在原有空間的基礎上進行擴增,返回值仍爲原空間的地址;②原有內存空間之後的空間不足:這種情況在進行內存擴增時,則在堆區重新找到一塊合適且連續的內存空間,並把原來空間的內容拷貝至新的內存上,最後返回新開闢內存空間的地址。在使用完所開闢的空間之後,需要使用free函數對開闢的空間進行釋放,釋放後的指針爲野指針,需要置爲空。若未釋放開闢的空間,則會造成內存泄漏的問題。

//函數原型
void *malloc(size_t size);  //開闢大小爲size的內存空間
int *ptr = (int *)malloc(1000);

void *calloc(size_t num, size_t size);   //開闢num個大小爲size的空間
int *ptr1 = (int *)calloc(100,sizeof(int));

void *realloc(void *ptr, size_t size);   //修改ptr指向的空間大小爲size
int *p = (int *)realloc(ptr, 100);

內存空間的開闢、驗證即釋放

int *ptr = (int *)malloc(100);
if(NULL == ptr){
    perror("malloc error ");
    return -1;
} 
//....對空間進行操作
free(ptr);
ptr = NULL;

3.柔性數組:用以解決結構體中需要變長數組的問題

在學習完動態內存分配之後,對於變長數組的空間開闢,我們首先想到的是進行動態內存分配,但是如果需要在結構體內定義一個變長數組該如何處理?對於這個問題有兩種解決方案,一種是對結構體和結構體內的變長數組使用兩次動態內存分配,另一種是使用柔性數組。在實際的操作中,第二種方式會明顯比第一種簡單,這裏所說的簡單主要體現在方便內存釋放上。下邊給出兩種方式下的編碼demo:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

struct a{
	int num;
	char arr[0];//利用柔性數組實現變長空間的數組開闢
};

struct array{
	int num;
	int *mem;  //指向變長的數組
};

int main()
{
	//方式2:
	struct a *p = (struct a*)malloc(sizeof(struct a) + 100 * sizeof(char));
	if (null == p){
		perror("error: ");
		return -1;
	}
	p->num = 100;
	for (int i = 0; i < p->num; i++){
		p->arr[i] = i;
	}
	free(p);

	//在結構體中形成變長的數組:方式一:
	struct array *arr = (struct array *)malloc(sizeof(struct array));
	if (null == arr){
		perror("error:");
			return -1;
	}

	arr->num = 100;
	arr->mem = (int *)malloc(arr->num*sizeof(int));
	if (null == arr->mem){
		perror("error:");
		free(arr);
		return -2;
	}

	//如何釋放空間:釋放由內向外,申請由外向內
	free(arr->mem);
	free(arr);

	system("pause");
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章