1. 为什么需要动态内存管理
我们先来看这样一个例子
C语言开辟空间的方式有两个特点
1.空间开辟大小是固定的
2.数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配
所以开辟空间的方式,就要试试动态内存开辟了
而在C语言中就有几个函数有内存管理的能力
malloc free calloc realloc
下面来说一下 动态内存管理 管理的是内存中的哪块地方
2.介绍几个动态内存函数
2.1 malloc和free
C语言提供了一个动态内存开辟函数:
头文件<stdlib.h>
这个函数向内存申请了一块连续可用的空间,返回的是指向这块空间的指针
假如 开辟成功,返回一个指向开辟好空间的指针
开辟失败,返回一个NULL指针
并且,返回值的类型是void* ,所以malloc函数并不知道开辟出来的空间类型,所以具体在使用时一定要看清楚类型
如果说参数size是0,malloc的行为是标准未定义的,这个取决于编译器
C语言也提供了一个专门用来做动态内存的释放和回收的函数free()
头文件 <stdlib.h>
如果参数 ptr 指向的空间不是动态开辟的,那么free()函数的行为是未定义的
如果参数 ptr 是NULL指针,那么函数啥事都不干
2.2 calloc
C语言还提供了一个和malloc极为相似的函数,来开辟空间。
头文件 <stdlib.h>
calloc 和malloc 的区别只在于,calloc函数会在返回地址之前把申请的空间的每个字节初始化化全为0
calloc()函数的功能是为 nitems 个大小为 size 的元素开辟一块空间,并把空间的每个字节初始化为0
2.3 realloc
C语言还提供了一个 比如说之前申请的空间太小了或者空间太大了,进行内存大小灵活调整的函数realloc
头文件<stdlib.h>
ptr 是要调整的内存地址,size 是调整之后新的大小,返回值 为调整之后的内存起始位置
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
realloc 在调整内存空间存在两种情况
如果后面有足够的空间
要扩展内存就直接在原有内存之后直接追加空间,原来空间的数据不会发生变化
如果后面没有足够的空间
要扩展内存就在堆空间上另找一个合适大小的连续空间来使用,这样的话函数返回的是一个新的内存地址
下面看这样一段代码
如果按照这样来扩充空间的话可能会造成
所以realloc 使用要这样
int mian()
{
int* ptr = (int*)malloc(100);
if (ptr != NULL)
{
//业务处理
}
else
{
exit(EXIT_FAILURE);
}
//扩展容量
//ptr = (int*)realloc(ptr, 1000);
int* p = NULL;
p = realloc(ptr, 1000);
if (p != NULL)
{
ptr = p;
}
//业务处理
free(ptr);
ptr = NULL;
return 0;
}
3. 常见的动态内存错误
3.1 对NULL指针的解引用操作
修改之后
3.2 对动态开辟空间的越界访问
3.3 对非动态开辟内存使用free释放
3.4 使用free 释放一块动态开辟内存的一部分
p到最后就指向了
p必须指向它的起始空间 ,然后再释放空间
3.5 对同一块动态内存多次释放
3.6动态开辟内存忘记释放(内存泄漏)
忘记释放不再使用的动态开辟的空间就会造成内存泄漏、
4.几个经典的笔试题目
1.运行Test会会出现什么错误
修改后
2.
3.
出现的问题就是str没有释放
4.
所以在free后一定要置位NULL
5.柔性数组
C99中,结构中的最后一个元素允许是未知大小的数组,这个叫柔性数组成员
5.1 柔性数组的特点
1.结构中的柔性数组成员前面必须至少一个其他成员
2.sizeof返回的这种结构大小不包括柔性数组的内存
3.包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小
5.2 柔性数组的使用
int i = 0;
type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
//业务处理
p->i = 100;
for(i=0; i<100; i++) {
p->a[i] = i; }
free(p);
5.3柔性数组的优势
1.方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用
free
可以释放结构体,但是用户并不知道这个结构体内的成员也需要
free
,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次
free
就可以把所有的内存也给释放掉。2.有利于访问速度连续的内存有益于提高访问速度,也有益于减少内存碎片
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/87391.html