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;
}

 

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