动态内存管理详解(malloc、realloc、calloc)

本文介绍了动态内存分配函数malloc,calloc,和realloc的用法,强调了它们在内存管理中的重要性,同时列举了动态数组常见的错误,如未检查返回值、内存越界、内存泄漏等,并提出了相应的解决方案。
摘要由CSDN通过智能技术生成

目录

用到的三个函数:

常见的动态数组错误:

内存泄漏?


用到的三个函数:

void* malloc (size_t size);
void* calloc (size_t num, size_t size);
void* realloc (void* ptr, size_t size);


size_t:无符号类型int,通俗来讲可以简单理解为只能为正整数

void*:无类型指针,需要我们自行定义,非常灵活与方便。

格式:

malloc:意为开辟了一个空间p,这个空间有10*4个字节,即40。事实上是开辟了10个空间,每个空间的大小是4个字节,存储int类型数据。

calloc:意为开辟了一个空间p,这个空间10个元素,每个元素大小是int。事实上也是开辟了10个空间,每个空间的大小是4个字节,存储int类型数据。

realloc:

其中你会malloc和calloc非常相似,作用也是一样的,怎么用看个人喜好。

realloc( (int*)s , sizeof(int) )函数:
函数返回会返回一个地址,而这个地址有两种可能。


1、:当s后面的存储空间不够开辟新的空间,那么就会重新找到一个新的足够大的地址开辟空间,返回新地址,这会导致一个隐患:内存碎片化,降低内存使用率
2、:s后面的空间足够开辟新的空间,那么追加,直接返回s的初始地址,
这两种情况下,返回的地址可能是s的原地址,也可能是新的地址
因此,在重新分配空间时,定义一个中间指针变量比较安全

realloc还有一种用法:realloc(NULL,40);//意为申请40个字节大小的存储空间


常见的动态数组错误:


1、当不做返回值判断,即不知道动态数组是否分配成功空间,直接对指针进行解引用赋值操作,例如*p = 20
如果分配失败,会出现解引用空指针的情况

2、对动态空间内存访问越界

3、对非动态申请空间进行free释放,这一块空间不是你动态申请的,你硬要free

4、使用free释放动态内存空间的一部分,而不是全部
例如:当用循环给p空间进行赋值时,p++,结束后,p的位置就不是原来的初始位置了,
那么此时释放空间就会出问题。
因为free只能释放初始位置的空间
要释放空间就要全部释放,而不是释放一部分
因此,以后的操作中,尽量不要让p动,不要让起始位置发生变化

5、对一块动态内存空间进行多次释放
解决办法:释放之后最好给p指针赋值为NULL,这样在多次free(NULL)也不会出现问题。因为释放空指针就没有什么好操作的,也就没什么错误

6、忘记释放空间(内存泄漏)
例如:

//在上述代码中,在函数中可能因为if条件直接return而导致p的空间并没有被释放,而到了主函数调用的时候,p指针已经结束了其生命周期,就是指针p已经不存在了,那我们就找不到这一块空间,连释空间的机会都还没有这种情况下,就会导致,内存泄露的bug。

内存泄漏?

就是内存没有被释放,这一块内存就被占据了,其他就用不了了
因此,要留给别人释放的机会

还有一个可能的BUg:返回局部变量的地址
在计算机有一个寄存器:独立的内存
return 就是将值存放在寄存器中,不会被销毁

例如:return c;//就是将c存放在寄存器当中
返回地址和返回值是不一样的。
如果返回地址,出来函数以后销毁内存,就找不到了,因此要避免返回局部变量的地址

局部变量在函数内,也就是在栈内,函数出栈后局部变量也会被销毁,
此时,如果返回某个局部变量或者函数的地址,就会出问题,这是返回栈空间地址的风险
而该地址指向的空间已经出栈还给操作系统,该指针尽管依旧指向该地址
如果访问,就是访问属于未分配的空间,这是一个野指针,属于非法访问。

注意:
calloc()函数会自动初始化空间,初始化为0
而malloc()函数不会自动初始化空间
申请空间有可能会失败,例如如果空间太大,内存不够用就会失败
realloc也有可能会申请空间失败,失败就是空指针,对野指针或空指针进行操作,属于非法访问内存

因此,尽量不要用原来的空间指针直接接受realloc,如果申请空间失败,返回NULL空指针,那么反而p原先存储的内容也直接没有了
int* ptr =  (int*)realloc(p,newNum * sizeof(int)) ;//不安全
所以这种赋值方式是不安全的

改后:

int* ptr = (int*)realloc(p,newNum * sizeof(int)) ;
if(ptr  != UNLL)
{
p = ptr;
}

动态申请内存完毕后,要free空间。
而事实上,空间还给操作系统之后,p指针依然存在,依旧记录着某地址,但是此时没有具体的指向,变化了野指针,此时就要p=NULL

因此,记住:申请和释放要成对出现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二十5画生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值