(C语言)动态内存管理

本篇文章计划用最简单的方式向大家介绍C语言动态内存管理这一问题

如果各位看官姥爷们觉得有用的话,不妨动动你们手指,点赞、评论、收藏哦!

目录

1.为什么需要动态内存分配

2.动态内存的介绍

2.1malloc和free

2.2calloc 

2.3realloc 

 3.常见的动态内存使用错误

3.1对空指针的解引用操作

3.2对动态空间进行越界访问

3.3 对非动态开辟空间使用free

3.4使用free释放动态内存的一部分

3.5对同一静态内存的多次释放

3.6忘记释放空间 

4.经典笔试题练手

         4.1练习一

4.2练习二

4.3练习三

4.4练习四

5.结语 


1.为什么需要动态内存分配

我们常见的内存开辟方式有:

int a = 20;//在栈空间上开辟四个字节
char arr[10] = { 0 };//在栈空间上开辟10个字节的连续空间

上述内存开辟方式有两个特点

1. 空间开辟大小是固定的。2. 数组必须指定数组的长度,以获取所需内存。

但是我们对于空间的需求,不仅仅是上述的情况。有时候我们需要根据情况来决定开辟空间的大小
此时动态内存的作用就凸显出来了


2.动态内存的介绍

2.1malloc和free

void* malloc(size_t size);

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。

  • 如果开辟成功,则返回一个指向开辟好空间的指针。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。 
  • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
void free(void* ptr);

C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收 

话不多说,直接上代码

int main()
{
	int arr[40] = {0};
	int* prt = (int*)malloc(40);//申请空间
	//检查
	if (prt == NULL)
	{
		perror("malloc");//检查错误的函数,要使用双引号,检查的是开辟空间的malloc
		return 1;
	}
	//初始化
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(prt + 1) = i;
	}
	//释放空间
	free(prt);//这里释放的是地址,因此不需要解引用
	prt = NULL;
	return 0;
}

2.2calloc 

C语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配,其具体使用我们结合下面一个函数来讲解

  • 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0
void* calloc(size_t num, size_t size);

2.3realloc 

  • realloc函数的出现让动态内存管理更加灵活
  • 当我们发现过去申请的空间太小或太大,那为了合理的使用内存,我们可以使用realloc 函数实现对动态开辟内存大小的调整
void* realloc(void* ptr, size_t size);

话不多说,让我们一起来看一下calloc和realloc代码的实现吧

int main()
{
	//申请空间
	//calloc需要两个参数(元素、每个元素类型的大小)
	//且在申请之初就会初始化空间为0
	int* ptr = (int*)calloc(10, sizeof(int));//ptr必须是指针
	
	//检查
	if (ptr == NULL)
	{
		perror("calloc");//打印错误
		return 1;
	}

	//打印
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(ptr + i));
	}
	//释放空间
	//free(calloc);

	//假设空间不够,需要扩容20个元素
	//原内存空间不够会重新寻找一块空间,将原有内存剪切到新的大空间上,并且把原空间释放
	int *p = (int*)realloc(ptr, 80);//20个整形需要80个字节
	if (*p != NULL)//防止内存不够,返回空指针
	{
		ptr = p;
	}
	//扩容成功
	free(ptr);
	ptr = NULL;
	return 0;
}

 3.常见的动态内存使用错误

3.1对空指针的解引用操作

即没有判空,在malloc等函数申请空间是有可能会申请到空指针;

解决方法:判空

3.2对动态空间进行越界访问

解决方法:弄清楚动态内存的边界

	for (i = 0; i <= 10; i++)//原申请空间<10,超过10会出现越界访问
	{
		printf("%d ", *(ptr + i));
	}

3.3 对非动态开辟空间使用free

必须在动态开辟空间的起始位置进行释放,否则可能会造成内存泄露(只申请,不归还)

3.4使用free释放动态内存的一部分

3.5对同一静态内存的多次释放

3.6忘记释放空间 


4.经典笔试题练手

4.1练习一

void GetMemory(char* p) //这里的指针p在函数结束之后就销毁了,没有将地址返回到Test函数中
{
	p = (char*)malloc(100);
}
void Test(void) {
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}

4.2练习二

char* GetMemory(void) 
{
	char p[] = "hello world";
	return p;
}
void Test(void) 
{
	char* str = NULL;
	str = GetMemory();//虽然str获取到了字符串的地址,但是由于上函数的销毁,原空间也不存在了,无法在进行访问
	printf(str);
}

4.3练习三

void GetMemory(char** p, int num) 
{
	*p = (char*)malloc(num);
}
void Test(void) {
	char* str = NULL;
	GetMemory(&str, 100);//如果不取地址将无妨修改str
	strcpy(str, "hello");
	printf(str);
	//忘记释放空间
	//free(str);
	//str = NULL;
}

4.4练习四

void Test(void) 
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	//str = NULL;//可以通过设置空指针避免此类问题
	if (str != NULL)
	{
		strcpy(str, "world");//free已经将空间还给操作系统了,这里的修改是非法修改
		printf(str);
	}
}

5.结语 

看到这里,相信老铁们对动态内存管理的知识已经有了基本的了解。

我是计算机海洋的新进船长Captain_ldx,如果我的文章能对您有帮助的话,麻烦各位观众姥爷们点赞、收藏、关注我吧!如果你对我的文章有任何问题或者意见,欢迎在评论区给我留言。后期更多知识点将持续更新......

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值