当前位置:网站首页>【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语言结构体里的数组和指针
边栏推荐
- Ant financial mobile testing tool solopi monitoring part of the source code guide.. Continuous update
- MySQL的触发器
- JS implementation of special prime numbers
- 新人如何入门学习软件测试
- C language to achieve minesweeping games
- 小白必看的软件测试发展路线
- 软件测试培训两个月骗局?培训机构到底如何选择?
- Firewalld防护墙
- Convert multidimensional object array to one-dimensional array
- 小白如何零基础学习软件测试?
猜你喜欢

Backup and restore of SNAT and DNAT firewall rules

ggplot2地图

解决Package is not available (for R ve【PACKAGE ‘XXX’ IS NOT AVAILABLE (FOR R VERSION X.Y.Z)” WARNING?】

Verilog daily question (vl4 shift operation and multiplication)

Vscode plug-in automatically adds comments

mmcv安装的办法

AMQP协议详解

MySQL高级-MVCC(超详细整理)

数据库优化——深入理解Mysql索引底层数据结构与算法

从非儿童网站看基线安全到底有多重要
随机推荐
谈谈你知道的发布上线(一)
软件测试工作内容太简单怎么办?
Punctual atomic serial port protocol
Redis源码剖析,狠狠地拿捏了,赶紧码住
JDWP未授权快速利用
MySQL面试题大全(陆续更新)
Shell脚本之AWK
R语言画图/绘图/作图2
面试官:算法刷题实录.pdf我居然答不上来
Distinguish between the export of ES6 and the module.exports of nodejs
区分ES6的export与Nodejs的module.exports的区别
解决Package is not available (for R ve【PACKAGE ‘XXX’ IS NOT AVAILABLE (FOR R VERSION X.Y.Z)” WARNING?】
Division optimization of JS decimal calculation on the Internet
LNMP source code compilation and installation
ng-repeat在迭代最后一个元素时执行一个方法
Ant financial mobile testing tool solopi monitoring part of the source code guide.. Continuous update
ionic中的$ionicPopup连续两个调用alert时需要注意的事项
零基础学习软件测试有什么条件?
Verilog daily question (vl4 shift operation and multiplication)
产品研发中第三方技术服务的管理