动态内存管理(介绍malloc,free,calloc,realloc函数)

在这里说的都是在堆区进行的空间开辟和释放

一、malloc函数

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

如果开辟成功,则返回一个指向开辟好空间的指针。但不会初始化开辟空间的内容

如果开辟失败.则返回一个NULL指针,因此malloc函数的返回值一定要做检查。

返回值的类型void*,所以malloc函数并不知道开辟空间的类型,所以要根据需求自己来决定

如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。
malloc申清的内存空间,当程序退出时,会还给操作系统

但是当程序不退出,动态申请的内存,不会主动释放,

需要使用free函数来释放。

free函数

如果参数Ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
int a = 1;
int* p = &a;
free(p);
比如这里就是错的用法


如果参数ptr是NULL指针则函数什么事都不做·

养成一个好习惯 在把空间释放后,把刚才开辟空间得到的起始指针赋为空指针,避免之后再次去使用它指向的一片已经归还给操作系统的空间

free函数底层原理是  在我们开辟动态内存空间时,一般情况下编译器会在你传的地址前多开辟4个字节来存放你记录的开辟的字节,再用free函数释放时实际上是从你传的地址的前四个字节开始释放,利用之前存在这的数据精准释放

注意   用free函数一次要释放就释放完,不能只释放一部分

          还有不要对同一块内存空间进行多次释放

         还有不要忘记用free函数进行开辟的动态内存的释放 ,比如说在函数内声明p创建指针变量来存放开辟空间的起始指针,当函数运行完退出去后,p被销毁相当于丢失了你开辟空间的首地址,相当于找不到这块空间,导致释放不了这个空间,并且也不能使用这块空间造成内存泄漏。动态申请的空间不会因为出了作用域就销毁(还给操作系统),只有两种方式销毁 第一 free函数 第二 程序结束(退出)

calloc函数

函数的功能是为num个大小为size的元素开辟一块空间,并目把空间的每个字节初始化为0。

与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
int main()
{
	
	int* p = calloc(10, sizeof(int));
	if (p==NULL)
	{
		perror("calloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
		printf("%d ", p[i]);
	free(p);
	p = NULL;
	return 0;
}

这里的结果是

就是因为calloc函数在开辟空间时会把空间的每一个字节都初始化为0

当释放完内存后,p就没用了,把p赋为空指针

当你申请的空间过大也有可能申请失败。

realloc函数

realloc函数的出现让动态内存管理更加灵活。 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存, 我们要对内存的大小做调整。 realloc 函数就可以起到作用

ptr是之前申请空间的起始地址,size表示的是新一次要申请的空间,但是如果ptr为空指针,realloc函数相当于调用了malloc函数

realloc函数有两种对空间的扩充方式

当原来开辟的空间的后面有足够的空间来满足你的扩容需求,那么编译器将在原来的基础上扩容,返回的地址也就是原来开辟空间的首地址

当原来开辟的空间的后面没有足够的空间来满足你的扩容需求,那么realloc函数将会进行一下四步

第一 开辟新的空间

第二 将旧空间的数据拷贝到新空间

第三 释放旧的空间

第四 返回新空间的地址

当然如果是减少空间,返回的就是刚才开辟的那个空间的起始地址,减少空间减少的部分归还操作系统

注意 当realloc函数在哪都无法将空间扩容时将会返回空指针

所以说

int main()
{
	int* p = calloc(10, sizeof(int));
	if (p==NULL)
	{
		perror("calloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
		printf("%d ", p[i]);
	p = (int*)realloc(p, 4000);
	
	for (i = 0; i < 1000; i++)
		printf("%d ", p[i]);
	free(p);
	p = NULL;
	return 0;
}

这种写法是不合理的,这里不适合把realloc函数的返回值直接赋给p指针,因为当realloc函数在哪都无法将空间扩容时将会返回空指针,导致之前申请的空间的起始地址没有了,以至于我们找不到刚才申请开辟的空间,并且也无法释放刚才开辟的空间,造成内存泄漏也就是既用不到那片内存空间,我也找不到了。

int main()
{
	int* p = calloc(10, sizeof(int));
	if (p==NULL)
	{
		perror("calloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
		printf("%d ", p[i]);
	int* str = (int*)realloc(p, 4000000000);
	if (str != NULL)
		p = str;
	for (i = 0; i < 1000; i++)
		printf("%d ", p[i]);
	free(p);
	p = NULL;
	return 0;
}

应该判断不为空指针后再赋给p

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值