前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C语言】动态内存管理(下)(realloc函数)

【C语言】动态内存管理(下)(realloc函数)

作者头像
埋头编程
发布2024-10-16 17:24:42
570
发布2024-10-16 17:24:42
举报
文章被收录于专栏:C/C++

前言

动态内存开辟(上)中我向大家介绍了malloc、calloc以及介绍动态内存常见的错误。那么在本文中,我将继续给大家介绍另一个非常重要且实用的动态内存管理的函数——realloc函数,以及再深入探讨一下free函数的使用细节,避免在使用动态内存函数时,由于不及时释放或者时胡乱释放所造成不必要的麻烦出现。

1. realloc

C语言中还有一个用于动态内存开辟的函数——realloc函数,其功能十分的重要。

为什么为会这么说呢? 这就要与realloc函数的功能挂钩了。大家不妨回想一下,无论是malloc或者是calloc申请的动态内存空间一旦申请了之后就无法再调整空间的大小(除非自己设置一小段代码,进行调整)。比如:有时我们发现过去申请的空间太小了,有时候又觉得申请的空间太大了,那为了合理的使用内存,我们一定会对内存的大小做灵活的处理。realloc函数就可以做到对动态内存开辟的空间进行调整。

realloc函数的功能:调整动态开辟后的空间大小。

realloc具体细节如下:

realloc
realloc
realloc
realloc

函数原型:void* realloc (void* ptr, size_t size)

  • ptr是指向要调整的内存起始地址
  • size是表示要内存调整之后总的大小,单位为字节
  • 返回值为调整之后内存空间的起始地址
  • 这个函数调整原内存空间的大小的基础上,还会将原来内存中的数据移动到新的空间中(也就是realloc申请的内存中)。
  • 不过要注意(记住):realloc函数在调整空间时,存在两种情况:
    • 情况1:原有空间之后有足够大的空间
    • 情况2:原有空间之后没有足够大的空间

2. realloc函数在调整空间时的细节

为了方便大家的理解,我用图解的方式再展示一遍realloc在调整空间时的情况。

realloc调整空间大小的情况
realloc调整空间大小的情况

2.1 针对情况1(realloc后面有足够的内存空间)

当是情况1的时候,要拓展内存就直接在原有的空间之后直接追加空间,原来空间的数据不会发生改变。

一句话概括:realloc后面的空间足够的话,直接在其后面调整内存大小即可。

2.2 针对情况2(realloc后面没有足够的内存空间)

当是情况2的时候,原有空间之后没有足够多的空间时,拓展的方法是:在堆空间上寻找另一个合适大小的连续空间来使用。这样函数返回的是一个新的内存起始地址。

2.3 realloc函数使用的注意事项

由于上述的两种情况,realloc函数在使用时就得注意一些细节的问题:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
int main()
{
 	int *ptr = (int*)malloc(100);
 	if(ptr != NULL)
 	{
 		//业务处理
 	}
 	else
 	{
		 return 1; 
	}
 	//扩展容量
 
 	//代码1 - 直接将realloc的返回值放到ptr中
	ptr = (int*)realloc(ptr, 1000);//这样可以吗?(如果申请失败会如何?)
 
 	//代码2 - 先将realloc函数的返回值放在p中,不为NULL,在放ptr中
 	int*p = NULL;
 	p = realloc(ptr, 1000);
 	if(p != NULL)
	{
		ptr = p;
 	}
 	//业务处理
 	free(ptr);
 	return 0;
}

我们一般使用realloc函数调整空间大小时,不会直接将要调整空间的起始地址作为接收realloc函数的返回值。因为,如果realloc函数在申请申请空间失败之后,会返回一个NULL值,也就说不仅realloc申请失败了就连之前申请的那块空间也找不到了。这就会造成严重的信息丢失的问题。

2.4 realloc的使用实例

题目:加入之前我创建的10个整型的数据空间不够用了,我想扩容到20个整形数据的大小,并插入数据。

代码语言:javascript
复制
int main()
{
	int* p = (int*)malloc(10*sizeof(int));
	if (p == NULL)
	{
		perror("malloc fail");
		return 1;
	}

	//向申请空间里面填入1~10的数据
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i + 1;
	}

	//到这里,突然我想扩容了,扩大到20个字节的大小,另外在这些数据的后面接着填入11~20的数据
	//----------------------------------------
	int* ptr = (int*)realloc(p,sizeof(int)*20);//只有强制类型之后我们才能随意操作这块内存空间
	if (ptr == NULL)
	{
		perror("realloc fail");
		return 1;
	}
		p = ptr; //这步得记住

	//-----------------------------------------
	for (int i = 10; i < 20; i++)
	{
		*(p + i) = i + 1;
	}

	for (int i = 0; i < 20; i++)
	{
		printf("%d ", *(p + i));
	}

	free(p);
	p = NULL;

	return 0;
}

上述的一些代码的具体细节需要读者们养成良好的编程习惯。多敲多练。

2.5 realloc函数的补充

realloc的函数原型为void* realloc(void* ptr, size_t size)。可能有些脑洞大开的读者就会想,如果我给形参ptr的值为NULL会发生什么情况。

给realloc形参中的ptr赋值为NULL就相当于malloc。也就是说,

realloc(NULL,40) == malloc(40)

还有就是,realloc函数在调整空间时属于第2种情况的话,其会自动释放之前的那块空间,不需要我们再手动释放了。 这点细节希望读者们牢记。

3.动态内存常见的错误

相信有不少读者在刚接触到动态内存管理时,总是会用出花来,而这些情况往往也是导致程序出现崩溃的罪魁祸首。 那就让我们来看看,有多少种我们常见的动态内存的错误用法。

3.1 对NULL指针的解引用操作

代码语言:javascript
复制
void test()
{
	int* p = (int*)malloc(INT_MAX / 4);
	*p = 20;//如果p的值为NULL,就会出现问题
	free(p);
}

3.2 对动态开辟的空间的越界访问

代码语言:javascript
复制
void test()
{
	int i = 0;
	int* p = (int*)malloc(10*sizeof(int));
	if(NULL == p)
	{
		exit(EXIT_FAILURE);
	}
	for(int i = 0;i <= 10;i++)
	{
		*(p+i) = i;//当i为10的时候就会出现越界访问的情况
	}
	free(p);
	p = NULL;
}

3.3 对非动态开辟内存使用free释放

代码语言:javascript
复制
void test()
{
	int a = 10;
	int* p = &a;
	free(p);//这个就是错误的,因为指针p指向的不是动态内存开辟的空间
}

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

代码语言:javascript
复制
void test()
{
	int*p = (int*)malloc(100);
	p++;
	free(p);//此刻的p不再是指向动态内存的起始地址了
}

3.5 对同一块内存空间多次释放

代码语言:javascript
复制
void test()
{
	int *p = (int*)malloc(100);
	free(p);
	free(p);//重复释放
}

3.6 动态开辟内存忘记释放(内存泄漏)

代码语言:javascript
复制
void test()
{
	int* p = malloc(100);
	if(NULL != p)
	{
		*p = 20;
	}
}

int main()
{
	test();
	whlie(1);
}

忘记释放不再使用的动态开辟的空间会造成内存泄漏。 切记:动态开辟的空间一定要及时释放,并且是正确的释放。

4.总结

在本文中,我们学习到了realloc的各种细节,以及动态内存常见的错误。希望读者们以后在写代码时尽量避免这些错误,否则程序就会陷入到水深火热之中。

结合动态内存管理(上)的内容,我们已经清楚的知道了动态内存开辟是怎么一回事了。总而言之,就是玩明白malloc、calloc、realloc、free这几个函数。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. realloc
  • 2. realloc函数在调整空间时的细节
    • 2.1 针对情况1(realloc后面有足够的内存空间)
      • 2.2 针对情况2(realloc后面没有足够的内存空间)
        • 2.3 realloc函数使用的注意事项
          • 2.4 realloc的使用实例
            • 2.5 realloc函数的补充
            • 3.动态内存常见的错误
              • 3.1 对NULL指针的解引用操作
                • 3.2 对动态开辟的空间的越界访问
                  • 3.3 对非动态开辟内存使用free释放
                    • 3.4 使用free释放一块动态开辟内存的一部分
                      • 3.5 对同一块内存空间多次释放
                        • 3.6 动态开辟内存忘记释放(内存泄漏)
                        • 4.总结
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档