动态内存管理

一、动态内存分配

在之前的操作中,我们都是在栈空间上开辟内存空间

如:

int key = 10;
char arr[10] = "abcdef";

但是这种开辟空间的方式存在几个问题;

        空间一旦开辟其大小是确定的

        对于数组来说,在创建的时候要给出数组长度,一旦确定数组长度无法调整

而在实际问题中,我们需要的空间大小有可能在程序运行时才能清楚,不能提前指定空间,那么原先这种开辟内存的方式就显得不够灵活。

因此,我们有了动态内存分配,旨在让我们自己可以灵活地申请和释放空间,其申请的空间在内存中的堆区

二、malloc

malloc是C语言提供的一个开辟内存的函数:

void* malloc (size_t size);

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

若开辟成功,返回指向该空间的指针,若开辟失败,返回NULL指针,因此要对其返回值进行判断

参数的返回类型是void*,可以任意,具体由我们自己决定

若传入的参数size是0 malloc函数的行为未定义,取决于编译器

具体我们来看怎么使用:

要注意,动态内存分配函数申请的大小都是以字节为单位的

在这里,我们看了开辟整型空间的效果,20个字节即5个整型,然后就可以对开辟的空间进行赋值打印等操作

当然,我们上面说了要判断返回的是否为空指针,使代码更安全

那么我们再来看一个结构体的例子:

如图,以上我们就成功为结构体开辟了空间,接下来就可以使用

三、free

free函数,是用来做动态内存的释放和回收的

上面我们讲了用malloc来开辟动态内存,那么当我们使用完后,就需要释放该空间还给操作系统,如果不释放,那么这块空间会一直存在,程序会吃掉内存,大大影响系统性能   。    

void free (void* ptr);

对于free函数,其接受类型为指针,该指针指向的是动态内存开辟出来的空间。

如果ptr指向空间不是动态开辟的,则free函数行为未定义

若ptr指向NULL指针,则free函数什么都不做

在我们上面的例子中,在使用完这块空间之后,是需要释放的 于是我们free(p) 然后将p置为空指针,那么将p置为空指针是否有意义呢?

在我们释放该空间之后,这块空间的使用权限还给操作系统,但是p依然指向这块空间,只不过不能再访问这次空间了,等下次操作系统重新分配空间,p很可能会成为野指针,在程序运行中很危险,因此我们有必要在释放后将p置为NULL

在我们刚刚创建的结构体中free和置空指针也是必须的,但是我们刚刚用malloc开辟了两次空间,那么应该先释放哪一个呢,顺序也很有考究。

如果我们先释放p,那么p指向的这个结构体的空间就不能被访问了,我们也就不能通过p访问结构体成员int*arr 然后释放arr  那么这时候p->arr就不能被释放,会给程序带来隐患,因此我们必须先释放p->arr 再释放p 记得还要都置为空指针

四、calloc

calloc也是用来动态内存分配的,其与malloc有一些区别

void* calloc (size_t num, size_t size);

参数num是元素个数,size是每个元素的大小,单位是字节

calloc函数会开辟num个size大小的元素空间,并且把空间的每个字节均初始化为0

用法与malloc几乎相同,只需要记得calloc会把字节全部初始化为0

五、realloc

尽管我们已经可以自己申请空间了,但有时候申请空间很大,有时候申请空间很小,我们应该怎么灵活调整呢 这时候我们就用到realloc函数调整动态开辟的内存的大小

void* realloc (void* ptr, size_t size);

ptr是要调整的内存地址,size是调整之后的新的大小 返回值是调整之后的内存的起始位置

注意:realloc函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

realloc在调整空间的时候存在两种情况:

1、原有空间之后有足够大的空间

当时这种情况的时候,要扩展内存就会直接在原内存之后继续追加空间,原来空间的数据不会变化

2、原有空间之后无足够大的空间

这种情况下,会找另一个合适大小的空间来使用,于是函数返回一个新的内存地址

如图,我们第一时间写出这样的代码,将20个字节的大小扩展到100个字节大小,并将返回的地址给p接收

但是,如果realloc扩容时失败了呢,会返回空指针,有风险,所以我们先判断返回地址

本节我简单介绍了动态内存分配的概念以及其中常用的几个函数,但是仅仅这些还不够,下节中我会为大家继续介绍动态内存分配中常见的一些错误等等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值