首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C】动态内存函数——大全(基本,简洁,包教会,适合初学)

【C】动态内存函数——大全(基本,简洁,包教会,适合初学)

作者头像
YY的秘密代码小屋
发布2024-01-22 20:22:03
发布2024-01-22 20:22:03
2980
举报
文章被收录于专栏:C++系列C++系列

前言:大家好,这里是YY;此篇博客主要是动态内存函数的知识点;包含【free】【malloc】【calloc】【realloc】【柔性数组】

PS:创作不易,每个知识点都有例题或者图帮助理解;如果对你有帮助,希望能够得到您的关注,赞,收藏,谢谢!

一.动态内存函数介绍


内存函数的头文件:

代码语言:javascript
复制
include<stdlib.h>

1.free

free函数用来释放动态开辟的内存。

  • 如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的
  • 如果参数ptr是NULL指针,则函数什么事都不做

使用场景:

代码语言:javascript
复制
int num=10;
int* p=NULL;
free(p);
p=NULL;

2.malloc

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

  • 如果开辟成功,则返回一个指向开辟好空间的指针
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要检查
  • 返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定
  • 如果参数size为0,malloc的行为是未定义的,取决于编译器

情景1:申请内存空间失败——返回空指针


情景2:动态内存的底层原理

  1. 局部变量特点,进函数时创建,出函数时销毁
  2. 局部变量放在栈区
  3. 动态内存分配放在堆区,不会自动摧毁,直到程序退出才释放。(易造成爆内存)

情景3:释放动态内存空间后还要把p置为空指针——防止野指针

释放动态内存空间后,p还会记得一个地址(野指针)

代码语言:javascript
复制
free(p);
p=NULL;

3.calloc

  • 函数的功能是为num个大小为size的元素开辟一块空间,并把空间每个字节都初始化为0
  • 与malloc的区别:只在于calloc会在返回地址之前把申请的空间每个字节全初始化为0

相当于calloc=malloc+memset


情景1:calloc开辟的值是0,而malloc开辟的空间没有初始化是随机值


4.realloc

  • ptr是要调整的内存地址
  • size是要调整后的新大小
  • 返回值为调整之后的内存起始位置
  • 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

情景1:realloc开辟失败,与malloc一样,返回的是NULL

解决方案:使用时也要判断,创建临时指针ptr来判断,如果成功再给p指针


情景2:realloc调整空间,分类讨论(内存空间足够与否)

  1. 当内存空间足够时,拓展方法:就直接原有内存之后直接追加空间,原来空间数据不发生变化,这样函数返回的是原内存地址
  2. 当内存空间不足时,拓展方法:在堆空间上另外找一个合适的连续空间来使用,这样函数返回的是一个新的内存地址

情景4:realloc调整空间时,申请内存的起始位置是空指针

申请内存起始位置是空指针时:等价于malloc

代码语言:javascript
复制
int*p=(int*)realloc(NULL,40);等价于malloc(40)

二.常见的动态内存错误


情景一:对空指针进行解引用

解决方法:判断指针是否为空


情景二:对动态开辟空间的越界访问


情景三:对非动态开辟的内存使用free释放 / 对同一块动态开辟的内存多次释放

解决方法:把p指针置为NULL,则无影响


情景四:使用free释放一块动态开辟内存的一部分

在释放时,p指针已经移动,指向的不再是动态内存空间的起始位置

解决方法:

  • 创建一个新指针ptr拷贝起始地址,遍历/移动指针时时用新指针ptr
  • 不改变"p指向的是动态内存空间的起始地址"的写法

情景五:未对动态开辟内存使用free释放——造成内存泄漏

指针会变成野指针,造成非法访问


三.几个经典的笔试题

例题1:
例题2:
例题3:内存泄漏
例题4:非法访问(野指针)

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


五.柔性数组

C99中,结构中的最后一个元素允许是未知大小的数组


柔性数组的两种写法:

有些编译器无法编译时,可以改成:


1.柔性数组的特点

  • 结构中的柔性数组成员前面必须至少有一个其他成员
  • sizeof返回这种结构大小,不包括柔性数组的内存
  • 包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小
  • 柔性数组的体现——可以更改数组的大小

2.用另一种方式实现柔性数组功能

法二:“单独malloc块空间,在此之上realloc”


两种方式的对比:

  • 第一种方式好处:方便内存释放
  • 第二种方式好处:有利于访问速度(连续的内存有益于提高访问速度)
  • 第二种方式坏处:要进行两次释放,容易造成内存泄漏
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.动态内存函数介绍
    • 内存函数的头文件:
    • 1.free
    • 2.malloc
      • 情景1:申请内存空间失败——返回空指针
      • 情景2:动态内存的底层原理
      • 情景3:释放动态内存空间后还要把p置为空指针——防止野指针
    • 3.calloc
      • 情景1:calloc开辟的值是0,而malloc开辟的空间没有初始化是随机值
    • 4.realloc
      • 情景1:realloc开辟失败,与malloc一样,返回的是NULL
      • 情景2:realloc调整空间,分类讨论(内存空间足够与否)
      • 情景4:realloc调整空间时,申请内存的起始位置是空指针
  • 二.常见的动态内存错误
    • 情景一:对空指针进行解引用
    • 情景二:对动态开辟空间的越界访问
    • 情景三:对非动态开辟的内存使用free释放 / 对同一块动态开辟的内存多次释放
    • 情景四:使用free释放一块动态开辟内存的一部分
    • 情景五:未对动态开辟内存使用free释放——造成内存泄漏
  • 三.几个经典的笔试题
    • 例题1:
    • 例题2:
    • 例题3:内存泄漏
    • 例题4:非法访问(野指针)
  • 四.C/C++程序的内存开辟
  • 五.柔性数组
    • 柔性数组的两种写法:
    • 1.柔性数组的特点
    • 2.用另一种方式实现柔性数组功能
    • 两种方式的对比:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档