动态内存分配malloc&&calloc&&realloc

本文详细介绍了C/C++中动态内存管理函数malloc、calloc和realloc的使用特点及实现,并列举了常见的动态内存错误,包括对NULL指针的解引用、越界访问、误释放非动态内存等问题,强调了正确释放内存的重要性。
摘要由CSDN通过智能技术生成


前言

本篇文章主要介绍malloc&calloc&realloc函数的使用、特点和可能出现的相关问题。


引入

为什么要引入这些动态空间申请函数里?
通俗的说就是:一方面可以说原有的固定空间已经满足不了你的需求,另一方面也可以说是为了空间的合理调配,避免造成空间的浪费。虽说计算机发展到了今天,空间的问题相比时间问的解决来说已是比较简单的了,扩容就可以解决一大部分问题,但是本着以最小的代价获得最大的收获,这样来说动态空间申请就派上了用场。
在这里插入图片描述

一、malloc函数

1.特点

malloc函数是一个动态空间申请函数
1>空间开辟的大小是固定的
2>数组在申明的时候,必须指定数组的长度,它所需的内存在编译时分配
3>在一些时候我们并不能准确知道我们所需的空间大小,这时候我们要使用动态空间开辟
4>mallo函数内部一个参数为所需分配的字节数大小
5>不会进行初始化

2.实现

void test1()
{
	int size = 10;
	int* p1 = (int*)malloc(sizeof(int) * size);//开辟10个int类型的空间
	int* p2 = (int*)malloc(size);//默认分配是以1个字节为单位
								//由于默认是(void*)类型,注意要进行强制类型转换
	//int* p3 = (int*)malloc(sizeof(int) * LLONG_MAX);//测试申请失败
	if (p1 != NULL)
	{
		printf("申请空间成功!\n");
		for (int i = 0; i < size; i++)
		{
			printf("%d ", *(p1 + i));
		}
	}
	else
	{
		perror("malloc:");
	}
	free(p1);
	p1 = NULL;
}

注意:在指针没有利用价值的时候一定要及时销毁并置为空!!!
提示:perror会指出错误类型。

二、calloc函数

1.特点

1>calloc函数有两个参数 num个数 size大小
2>函数会进行自动初始化 全部初始化为0
3>相比较malloc会方便一点点

2.实现

void test2()
{
	int size = 10;
	int* p1 = (int*)calloc(size,sizeof(int));//开辟10个int类型的空间

	int* p3 = (int*)calloc(LLONG_MAX,sizeof(int));//测试申请失败
	if (p1 != NULL)
	{
		printf("申请空间成功!\n");
		for (int i = 0; i < size; i++)
		{
			printf("%d ", *(p1 + i));
		}
	}
	else
	{
		perror("malloc:");
	}
	free(p1);
	p1 = NULL;
}

三、realloc函数

1.特点

1>relloc相比malloc和calloc更加灵活
2>有时我们会发现过去申请的空间小了,有时候我们会感觉申请的空间大了,这时relloc就派上用场了
3>要是我们预先申请的空间不够了,我们可以用relloc进行扩容,( 要是本身后面有足够的空间话就直接往后续) relloc函数会调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间, 并且自动把地址改为新的,自动释放原来的
4>函数类型为(void*)
5>注意最后的空间大小一共是新的申请的大小,而不是在原来的基础上又加了新的大小
6>通俗的说就是说这个地方容不下你的发展了,去给你找个新的地方发展,原来的地方释放掉

2.实现

void test3()
{
	int* p = (int*)malloc(100);//malloc开辟100字节空间
	//p的地址:0000027C13749A50
	if (p != NULL)
	{
		printf("申请成功!\n"); 	
	}
	else
	{
		perror("malloc:");
	}
	//扩展容量
	p = (int*)realloc(p, 1000); 
	//p的地址:0000027C13752890


	//下面为第二种方式扩容,自己新创建个指针变量,其实没必要这样我个人认为
	//int* p1 = NULL;
	//p1 = relloc(p, 1000);
	//if (p != NULL)
	//{
	//	printf("申请成功!\n");
	//}
	//else
	//{
	//	perror("malloc:");
	//}
	free(p);
	//free(p1);
	p = NULL;
	//p1 = NULL;
}

四、常见动态内存错误

1.对NULL指针的解引用操作

void test4()
{
	int* p = (int*)malloc(INT_MAX / 4);
	*p = 20;
	//如果p的值是NULL,就会有问题。 加入assert()可以准确定位到错误位置
	free(p);
	p = NULL;
	//一定要养成不用的时候给释放掉并且给NULL
}

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

void test5()
{
	int i = 0;
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc:");
	}
	else
	{
		for (i = 0; i <= 10; i++)
		{
			*(p + i) = i;
			//当i=10时为越界访问
			//运行时会出错
			printf("%d", *(p + i));
		}
	}
	free(p);
	p = NULL;
}

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

void test6()
{
	int a = 10;
	int* p = &a;
	free(p);//error 不是动态内存开辟的空间不能用free释放
	p = NULL;
}

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

void test7()
{
	int* p = (int*)malloc(100 * (sizeof(int)));
	p++;
	free(p);//这样是错误的,不能进行部分空间释放,
	        //也不是从这个地方开始释放固定大小的空间
	p = NULL;
}

5.对一片空间多次进行释放

void test8()
{
	int* p = (int*)malloc(100 * (sizeof(int)));
	free(p);
	free(p);//error 不能多次释放
}

6.对动态开辟的内存忘记释放(内存泄漏)

void test99()
{
	int* p = (int*)malloc(100 * (sizeof(int)));
	if (p != NULL)
	{
		*p = 20;
	}
}
void test9()
{
	test99();
	while (1);//这样内存会一直往上涨,但是我们一般关闭这个窗口后就停止了
	          //编译器会帮助我们会释放掉
}

注:编者水平有限,若有错误,敬请指正!!!

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值