解密动态内存管理的奥秘(含内存4个函数)


目录

一.为什么存在动态内存管理

二.动态内存函数的介绍

1. malloc函数(memory  alloc  内存开辟)

函数介绍:

malloc函数使用举例代码:

2.free(释放) 

函数介绍:

代码的示例:

3.calloc

函数介绍:

代码示例:

运行结果:

4.realloc

函数介绍:

使用示例代码:

常见的动态内存管理的错误

1.对NULL指针进行解引用操作

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

3.对非动态开辟的空间使用free

4.使用free释放一块动态开辟的内存中的一部分

5.对同一块内存多次释放

6.动态内存开辟忘记释放,造成内存泄漏


一.为什么存在动态内存管理

我们常见的内存开辟方式:

int  a =  20;               //在栈空间上开辟四个字节

int  arr[10] = { 0 };     //在栈空间上开辟40个字节

但是上的开辟空间方式有两个特点:

1.开辟的空间的大小是固定的;

2.数组在申明的时候,必须指定固定的长度,它所需的内存在编译时分配,有可能用不完造成浪费,也有可能后期不够用;

但是下在我们实际所需求中,不仅仅是上面的两种情况,有时候我们需要的空间大小在程序运行时才知道,那么上述方式开辟空间就不能够满足,所以有了动态内存开辟。

二.动态内存函数的介绍

必备知识:

内存大概的划分:

栈区: 主要存放局部变量,形式参数等等

堆区: 动态内存的开辟,malloc,free,calloc,realloc等等

静态区: 全局变量,静态变量等等

1. malloc函数(memory  alloc  内存开辟)

函数介绍:

void*   malloc(size_t    size)

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

值得注意的是:

1. 如果开辟成功,将返回一个指向开辟好了的空间的指针;

如果开辟失败,将返回空指针NULL;

所以在开辟后需要判断是否开辟成功,检查返回值;

2. 函数返回的是空指针,malloc函数并不知道开辟空间的类型,所以在使用的时候需要自己决定(使用强制类型转换);

3.如果size为0时,malloc函数的行为是未定义的,取决于编译器;

4.malloc函数开辟的空间里面存放的是随机值(下面代码可验证);

5.malloc函数申请的空间,当程序退出时,还给操作系统,当程序不退出时,动态开辟的空间不会主动还给操作系统,需要用free函数来释放;

malloc函数使用举例代码:

int main()
{int* p = (int *)malloc(40);   //这里需要的是int*类型的指针,所以用()强制类型转换为int*if (p == NULL){perror(malloc);           //判断是否开辟成功return 1;}int i = 0;for (i = 0; i < 10; i++){printf("%d\n",*(p+i));}free(p);p=NULL;         //将p置为空指针,不要让p成为野指针return 0;
}

运行结果:

-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451

2.free(释放) 

函数介绍:

void*   free (void*  p)

C语言提供的free函数是专门用来做动态内存的释放和回收的

free是用来释放动态开辟的内存

1.如果void* p所指向的内存不是动态开辟的,free函数的行为是未定义的;

2.如果void* p所指向的是NULL(空指针),则free函数什么都不做;

代码的示例:

int main()
{int* p = (int *)malloc(40);   //这里需要的是int*类型的指针,所以用()强制类型转换为int*if (p == NULL){perror(malloc);           //判断是否开辟成功return 1;}int i = 0;for (i = 0; i < 10; i++){printf("%d\n",*(p+i));}free(p);       //使用完该空间后释放p=NULL;         //将p置为空指针,不要让p成为野指针return 0;
}

3.calloc

函数介绍:

void*   calloc (size_t  num , size_t   size)

功能:是为num个大小为size的元素开辟一块空间,并吃初始化为0;

与malloc函数类似,只是会将开辟的空间内容初始化为0;

代码示例:

int main()
{int* p = (int* )calloc(40,sizeof(int));if (p == NULL){perror(calloc);return 1;}int i = 0;for (i = 0; i < 10; i++){printf("%d ",*(p+i));}free(p);p = NULL;return 0;
}

运行结果:

0   0   0   0   0   0   0   0   0   0

4.realloc

realloc函数可以让内存管理更加灵活;

函数介绍:

viod*   realloc    (void*   ptr,size_t   size)

realloc函数可以调整我们申请的空间的大小;

其中ptr是要调整的内存地址;

size是调整之后的大小;

返回值是为调整之后的内存起始位置;

当void*  ptr  为一个空指针时,功能和malloc一样;

值得注意的是:这个函数调整之后,可能将原来内存中的数据移动到新的空间;

分为两种情况;

1.原有空间的后面有足够大的空间时(即原有空间后面的剩余空间有所需增加空间那么大),就直接在原有空间后面开辟,并且返回指向原来空间的指针;

2.当原有的空间后面没有足够大的空间来增加空间,则需要重新找一个空间开辟,并且将原有空间的内容复制过去,然后释放旧的空间的内存,返回新的地址;

使用示例代码:

int main()
{int* p =(int* )malloc(40);if (p == NULL){perror("malloc");return 1;}int i = 0;for (i = 0; i < 10; i++){p[i] = i+1;}int* ret = realloc(p,80);{if (ret == NULL){perror("realloc");return 1;}else{p = ret;}}for (i = 0; i < 20; i++){printf("%d ",*(p+i));}free(p);p = NULL;return 0;
}

运行结果:

1  2  3  4  5  6  7  8  9  10  -842150451  -842150451  -842150451  -842150451  -842150451  -842150451  -842150451  -842150451 -842150451 -842150451

常见的动态内存管理的错误

1.对NULL指针进行解引用操作

      void   test

     {   

              int  *p  =  (int *)malloc(INT_MAX);

              *p = 20;    //如果p是空指针就有问题;

               free(p);

     }

当用内存函数开辟好空间后,不检查是否开辟成功就直接使用;

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

int* p = (int*)malloc(40);

int i = 0;

for(i=0;i<12;i++)                  //  i=10,11,就越界访问了

{

     printf("%d ",*(p+i));

}

3.对非动态开辟的空间使用free

int a = 10;

int* p = &a;

free(p);            //  错误的

4.使用free释放一块动态开辟的内存中的一部分

int* p=(int *)malloc(40);

p++;

free(p);           //p++后,已经不是指向的原开辟的内存,而是指向的一部分;

5.对同一块内存多次释放

int* p = (int*)malloc(40);

free(p);

free(p);

6.动态内存开辟忘记释放,造成内存泄漏

void   test()

{

         int * p =(int*)mmalloc(40)

          if(NULL!=p)

          {

                 *p=20;

          }

                                                     //使用完后忘记释放,出函数p销毁,但是40个字节的空间还在

int  main()

{

         test();

          while(1);                               //死循环,程序不结束,40个字节永远用不到

}

                                                             作者:GOXXT

                                                             专注分享在学习道路上的知识笔记



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/6509.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#WinForm获取当前活动子窗体使用鼠标滚轮事件改变窗体大小

获取当前活动子窗体使用鼠标滚轮事件改变窗体大小&#xff0c;实例在文末&#xff0c;可下载。 这个主要分三个重点 第一步 我们需要让子窗体显示在父窗体中 Form22 new Form2(); Form22.TopLevel false; // 不是顶级窗体 //Form22.Parent this;// 设置父窗体 一定不要…

配置NFS服务

环境 环境 ubuntu 10.4 vm 7.1 终端 ifconfig 得到 ubuntu资料 INET ADDR 192.168.0.4 BCAST 192.168.0.255 MASK 255.255.255.0 操作前先关闭防火墙 关闭防火墙&#xff1a; 命令&#xff1a;sudo ufw disable 打开防火墙 命令&#xff1a;sudo ufw enable 配置过程 一 安…

机器人SLAM导航学习-All in one

参考引用 张虎&#xff0c;机器人SLAM导航核心技术与实战[M]. 机械工业出版社&#xff0c;2022.本博客未详尽之处可自行查阅上述书籍 一、编程基础篇 1. ROS 入门必备知识 ROS学习笔记&#xff08;文章链接汇总&#xff09; 2. C 编程范式 《21天学通C》读书笔记&#xff0…

RabbitMQ

文章目录 RabbitMQ初识MQ同步和异步通讯同步通讯异步通讯 技术对比 RabbitMq安装RabbitMQ架构RabbitMQ消息模型publisher实现consumer实现总结 SpringAMQPBasic Queue 简单队列模型WorkQueue发布/订阅FanoutDirectTopic 消息转换器 RabbitMQ 初识MQ 同步和异步通讯 微服务间…

力扣刷题SQL-197. 上升的温度---分步解题

表&#xff1a; Weather ------------------------ | Column Name | Type | ------------------------ | id | int | | recordDate | date | | temperature | int | ------------------------ id 是这个表的主键 该表包含特定日期的温度信息编…

【C语言】指针进阶(3)

目录 指针和数组笔试题解析 一维数组 字符数组 二维数组 指针笔试题 在前面两篇文章&#xff0c;我们已经学完了指针进阶的所有知识点。在这篇文章中&#xff0c;我们主要学习的是一些常见的笔试题的总结。 指针和数组笔试题解析 在做题之前&#xff0c;我们先复习一下之…

AC自动机(java)

AC自动机 AC自动机介绍代码演示 indexTree AC自动机介绍 AC自动机算法是一种基于Trie树和有限状态机的字符串匹配算法。它在查找字符串时&#xff0c;利用额外的失配指针进行回退&#xff0c;转向其他分支&#xff0c;避免重复匹配前缀&#xff0c;从而提高算法效率。当一个字典…

Docker 教程

Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱机制&a…

【CSDN竞赛】练习题(练手题)及解析(含代码+注释):小玉家的电费;饿龙咆哮-逃离城堡;收件邮箱;寻找宝藏山

订阅专栏,学习更多干货知识! 为想要参与CSDN竞赛的朋友提供几道练手题目及解决方案。含有题目描述以及不同编程语言的解决方案。 💿目录 🏮一、题目一:小玉家的电费📂1.1 题目描述📂1.2 示例代码🏮二、题目二:饿龙咆哮-逃离城堡📂2.1 题目描述📂2.2 示例代码…

什么是Redis?

什么是Redis 什么是Redis一、特性1. 支持多种数据结构2. 读/写速度快&#xff0c;性能高。3. 支持持久化。4. 实现高可用主从复制&#xff0c;主节点做数据副本。5. 实现分布式集群和高可用。 二、基本数据类型string&#xff08;字符串&#xff09;list(双向链表)set(集合)zse…

基于Java+SpringBoot+Vue前后端分离旅游网站详细设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

UE5 AI移动无动作问题

文章目录 问题背景解决方法问题背景 在使用行为树让角色移动时,出现角色行走不播放动作的情况: 解决方法 其实有2个问题导致出现这种情况 1、角色动画蓝图的问题 角色动画蓝图可能存在4个问题: ① 无播放行走动画 ② 速度的值未正常传递 ③ 播放移动动作逻辑的值判断错…

Windows Docker部署springboot微服务

Windows Docker部署springboot微服务 前言 偶然的机会让我能够实操在Windows server 2019版本的服务器上进行springCloud服务的部署 过程中深刻的体会到了为什么Docker要推荐使用Linux系列的系统进行操作 遇到的问题 springboot镜像打包微服务启动后nacos连不上使用的基础…

[SSM]手写Spring框架

目录 十一、手写Spring框架 第一步&#xff1a;创建模块myspring 第二步&#xff1a;准备好要管理的Bean 第三步&#xff1a;准备myspring.xml配置文件 第四步&#xff1a;核心接口实现 第五步&#xff1a;实例化Bean 第六步&#xff1a;给Bean属性赋值 第七步&#xff…

使用nginx和ffmpeg搭建HTTP FLV流媒体服务器(摄像头RTSP视频流->RTMP->http-flv)

名词解释 RTSP &#xff08;Real-Time Streaming Protocol&#xff09; 是一种网络协议&#xff0c;用于控制实时流媒体的传输。它是一种应用层协议&#xff0c;通常用于在客户端和流媒体服务器之间建立和控制媒体流的传输。RTSP允许客户端向服务器发送请求&#xff0c;如…

【Java基础教程】(四十二)多线程篇 · 上:多进程与多线程、并发与并行的关系,多线程的实现方式、线程流转状态、常用操作方法解析~

Java基础教程之多线程 上 &#x1f539;本节学习目标1️⃣ 线程与进程&#x1f50d;关于多进程、多线程、并发与并行之间的概念关系&#xff1f; 2️⃣ 多线程实现2.1 继承 Thread 类2.2 实现 Runnable 接口2.3 多线程两种实现方式的区别2.4 利用 Callable 接口实现多线程2.5 …

00_ubuntu_开发环境的搭建

ubuntu 的版本22.04 2023-07-21 1.卸载firefox dpkg --get-selections |grep firefox // 查看安装包的信息 sudo apt-get purge firefox firefox-locale-en firefox-locale-zh-hans // 卸载相应的包 2.下载google安装包并安装 wget https://dl.google.com/linux/direct/goo…

深度学习——过拟合和Dropout

基本概念 什么是过拟合&#xff1f; 过拟合&#xff08;Overfitting&#xff09;是机器学习和深度学习中常见的问题之一&#xff0c;它指的是模型在训练数据上表现得很好&#xff0c;但在未见过的新数据上表现较差的现象。 当一个模型过度地学习了训练数据的细节和噪声&#…

【多模态】17、CORA | 将 CLIP 使用到开集目标检测

文章目录 一、背景二、方法2.1 总体结构2.2 region prompting2.3 anchor pre-matching 三、效果 论文&#xff1a;CORA: Adapting CLIP for Open-Vocabulary Detection with Region Prompting and Anchor Pre-Matching 代码&#xff1a;https://github.com/tgxs002/CORA 出处…

Qt/C++音视频开发48-推流到rtsp服务器

一、前言 之前已经打通了rtmp的推流&#xff0c;理论上按照同样的代码&#xff0c;只要将rtmp推流地址换成rtsp推流地址&#xff0c;然后格式将flv换成rtsp就行&#xff0c;无奈直接遇到协议不支持的错误提示&#xff0c;网上说要换成rtp&#xff0c;换了也没用&#xff0c;而…