当前位置:网站首页>【C语言笔记分享】——动态内存管理malloc、free、calloc、realloc、柔性数组
【C语言笔记分享】——动态内存管理malloc、free、calloc、realloc、柔性数组
2022-07-28 16:31:00 【发疯的橙子】
文章目录
1.为什么会存在动态内存分配
int val = 20;//在栈空间上开辟4个字节
char arr[10]={
0};//在栈空间上开辟10个字节的连续空间
- 上述代码开辟空间的方式有两个特点:
- 空间开辟的大小是固定的。
- 数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时就分配。
- 对于空间的需求,不仅是上述的情况,有时候需要的空间大小在程序运行的时候才能知道,那数组在编译时开辟空间的方式就不能满足了。
2.动态内存的函数的介绍
注:所有动态开辟的空间是在堆区开辟的!

2.1 malloc 和 free
- malloc和free都声明在
stdlib.h头文件中。
2.1.1 malloc使用
malloc(函数链接)
void* malloc (size_t size);
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个
NULL指针,因此malloc的返回值一定要做检查! - 返回值的类型是
void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候由使用者自己来决定。 - 如果参数
size为0,malloc的行为是标准未定义的,取决于编译器。(开辟0字节空间不代表是错的) - 频繁使用
malloc开辟空间会导致内存碎片
- [ ]作用:向内存申请一块
连续可用的空间,并返回指向这块空间的指针。
- 例子:

2.1.2 free 使用
free(函数链接)
void free (void* ptr);
如果参数
ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。(不代表只能释放动态开辟的内存)如果参数
ptr是NULL指针,则函数什么事也不做对同一块空间,进行多次
free释放,是不会报错的,但是建议不要多次释放作用:用来释放动态开辟的内存。
- 例子:

- 例子:
2.2 calloc
calloc(函数链接)
void* calloc (size_t num, size_t size);
calloc也是用来动态内存分配。- 与函数
malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
- [ ]作用:为
num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0。
- 例子:

2.3 realloc
realloc(函数链接)
void* realloc (void* ptr, size_t size);
realloc函数的出现让动态内存管理更加灵活。realloc函数可以做到对动态开辟内存大小的调整(扩大内存,减小内存)ptr是要调整的内存地址。size调整之后的新大小- 返回值为调整之后的内存起始位置。
- 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到
新的空间。 - 在使用
realloc追加内存时,不可使用原指针变量接收(ptr),需要创建新的指针变量接收,防止realloc申请空间失败,导致原指针(ptr)为空指针 realloc在调整内存空间的是存在两种情况:
情况1.原有空间之后有足够大的空间
情况2.原有空间之后没有足够大的空间

情况1:当是情况1的时候,要扩展内存就在原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2:原有空间之后没有足够多的空间时,
扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的就是一个新的内存地址。
- 例子:

扩容,地址
可能发生变化,对比以下三张运行截图
以下是情况2:
原有空间之后没有足够多的空间时,
在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的就是一个新的内存地址。



3.常见的动态内存错误
3.1 对NULL指针的解引用操作

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

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

3.4 使用free释放一块动态开辟内存的一部分
释放动态开辟的空间必须从起始地址释放,只释放一部分内存是做不到的!

3.5 对同一块动态内存多次释放

3.6 动态开辟内存忘记释放(内存泄漏)

忘记释放不再使用的动态开辟的空间会造成内存泄漏。
切记:动态开辟的空间一定要释放,并且正确释放
4.经典的笔试题
- 例子:
printf(str);==printf("abcd");
相当于把str首地址给了printf
char* p ="abcd";//p只是a的地址
printf(p);

- 1.正确修改:址传递

- 2.正确修改:函数返回值

5. C/C++程序的内存开辟

C/C++ 程序内存分配的几个区域:
- 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。栈区主要存放运行函数而分配的
局部变量、函数参数、返回数据、返回地址等。 - 堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。分配方式类似于
链表。存放malloc、realloc、calloc开辟的空间和free。 - 数据段(静态区 static):存放
全局变量、静态数据。程序结束后由系统释放。 - 代码块:存放
函数体(类成员函数和全局函数)的二进制代码
6.柔性数组
也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。
例如:
- 有些编译器会报错无法编译,可以改成:

6.1 柔性数组的特点
- 结构小红的柔性数组成员前面必须至少有一个其他成员。
sizeof返回的这种结构大小不包括柔性数组的内存。- 包含柔性数组成员的结构用
malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小
例如:

6.2 柔性数组的使用
柔型数组方案 :一次
free、malloc
这样柔性数组成员a,相当于获得了100个整形元素的连续空间。如果觉得
malloc开辟的空间小了,就可以使用realloc调整大小。

6.3柔性数组的优势
不是柔性数组的方案:2次
free、malloc,其次malloc使用越多,内存碎片可能性就会越多

1.第一个好处是: 方便内存释放
如果我们的代码实在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用
free可以释放结构体,但是用户并不知道这个结构体成员也许要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户一次free就可以把所有的内存也给释放掉。
2. 第二个好处是:这样有利于访问速度。
连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)
扩展阅读(超链接)
C语言结构体里的数组和指针
边栏推荐
- Can‘t use an undefined value as an ARRAY reference at probe2symbol
- 软件测试培训两个月可以就业吗?
- MySQL PgSQL realizes the merging of multiple lines of records into one line, grouping and merging, and dividing with specified characters
- MySQL implements sorting according to custom (specified order)
- About standard IO buffers
- [Presto] common commands of Presto
- 2021 年全国大学生数据统计与分析竞赛
- Uparse rich text style of uni app
- AMQP protocol details
- 产品研发中第三方技术服务的管理
猜你喜欢

掌握JVM面试专题和答案Offer拿到手软(附学习路线图)

数据库性能分析与优化(爱测未来团队内训材料)

How important is baseline safety from non child websites

Esp-mqtt-at instruction connects Alibaba cloud Internet of things platform

easyui tree

Using OCR to reverse recognize text content in airtest

Talk about the measurement of "post release problems"

技术面轻松通过,HR:只有三年大厂经验的不值20K

Firewall protective wall

简单易用的APP专项测试工具iTest4.7.0发布啦
随机推荐
Editor MAVON editor for offline use
想转行IT,非科班出身真的不要紧吗?
Export word according to the template, generate compound format tables and variable column tables
蚂蚁金服移动测试工具solopi监控部分源码导读。。持续更新
C language to achieve minesweeping games
特殊质数js实现
[sqoop] sqoop 1.4.7 installation integration cdh5.13
软件测试就业前景怎么样?
easyui tree
Encrypt the video and upload it to OSS to achieve high concurrent access
ggplot2地图
Deploy lamp platform -- compilation and installation of Linux, Apache, MySQL and PHP
Management of third-party technical services in product development
软件测试工作内容太简单怎么办?
软件测试的培训机构靠谱吗
Convert the image file of input type='file'to Base64
如何看软件测试未来的发展?
dos命令大全 基础命令+网络的常用命令
渗透测试大杀器kali安装配置
你能读懂这个故事吗?