C系列-动态内存管理

 🌈个人主页: 会编程的果子君
💫个人格言:“成为自己未来的主人~” 

 

目录

 为什么要有动态内存分配

malloc和free

malloc

free

calloc和realloc

calloc

realloc

常见的动态内存的错误

对NULL指针的解引用操作

 ​编辑  

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

 ​编辑  

对非动态开辟内存使用free函数

使用free函数释放一块动态开辟内存的一部分

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


 为什么要有动态内存分配

我们已经掌握的内存开辟方式有:

int val = 20;//在栈空间上开辟4个字节
char arr[10] = { 0 };//在栈空间上开辟10个字节的连续空间

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

  • 空间开辟大小是固定的
  • 数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能调整 

但是对于空间的需求,不仅仅是上述的情况,有时候我们需要的空间大小在程序运行的时候我们才能知道,那数组的编译时开辟空间的方式就不能满足了。

C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,就比较灵活

malloc和free

malloc

c语言提供了一个动态内存开辟的函数

void* malloc(size_t size);

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

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

free

C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收的,函数原型如下:

void free(void* str);

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

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

malloc和free都声明在stdlib.h头文件当中

举个例子:

#include<stdio.h>
#include<stdlib.h>int main()
{int arr[10] = { 0 };int* ptr = NULL;ptr=(int*)malloc(10 * sizeof(int));if (ptr != NULL){int i = 0;for (i = 0; i < 10; i++){*(ptr + i) = i;}}free(ptr);//释放ptr所指向的动态内存ptr = NULL;return 0;
}

calloc和realloc

calloc

C语言还提供了一个函数叫calloc,calloc函数也用来动态内存分配 ,原型如下:

void* calloc(size_t num, size_t size);

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

举个例子:

#include<stdio.h>
#include<stdlib.h>
int main()
{int* p = (int*)calloc(10, sizeof(int));if (NULL != p){int i = 0;for (i = 0; i < 10; i++){printf("%d ", *(p + i));}}free(p);p = NULL;return 0;
}

 

 所以如果我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务

realloc

  • realloc函数的出现让动态内存管理更加灵活
  • 有时我们发现过去申请的空间太小了,有时候我们又觉得申请的空间过大了,所以为了合理的分配内存,我们一定要学会对内存的大小做灵活的调整,那realloc函数就可以完成这个工作

函数原型如下:

void* realloc(void* ptr, size_t size);

  • ptr是要调整的内存地址
  • size是调整之后的新大小
  • 返回值为调整之后的内存起始位置
  • 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
  • realloc在调整内存空间是存在两种情况
  1.  原有空间之后有足够大的空间
  2. 原有内存之后没有足够大的空间

1.要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不会发生变化

2.原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。

由于上述的两种情况,realloc函数的使用就要注意一些

#include<stdio.h>
#include<stdlib.h>int main()
{int* ptr = (int*)malloc(100);if (ptr != NULL){//业务处理}else{return 1;}//拓展容量//代码1-直接将realloc的返回值放到ptr中ptr = (int*)realloc(ptr, 1000);//申请失败的话会怎么样?//代码2-先将realloc函数的返回值放到p中,不为NULL,在放到ptr中int* p = NULL;p = realloc(ptr, 1000);if (p != NULL){ptr = p;}//业务处理free(ptr);ptr = NULL;return 0;
}

常见的动态内存的错误

对NULL指针的解引用操作

#include<stdio.h>
#include<stdlib.h>
void test()
{int* p = (int*)malloc(INT_MAX / 4);*p = 20;//如果p的值是NULL,就会有问题free(p);
}int main()
{test();return 0;
}

   

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

#include<stdio.h>
#include<stdlib.h>
void test()
{int i = 0;int* p = (int*)malloc(10 * sizeof(int));if (NULL == p){perror("malloc");}for (i = 0; i <= 10; i++){*(p + i) = i;//当i是10的时候越界访问}free(p);
}
int main()
{test();return 0;
}

   

对非动态开辟内存使用free函数

 

#include<stdio.h>
#include<stdlib.h>
void test()
{int a = 10;int* p = &a;free(p);//ok?
}
int main()
{test();return 0;
}

使用free函数释放一块动态开辟内存的一部分

 

#include<stdio.h>
#include<stdlib.h>
void test()
{int* p = (int*)malloc(100);p++;free(p);//p不再指向动态内存的起始位置
}
int main()
{test();return 0;
}

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

#include<stdio.h>
#include<stdlib.h>
void test()
{int* p = (int*)malloc(100);if (NULL != p){*p = 20;}
}
int main()
{test();while (1);
}

忘记释放不再使用的动态开辟的空间会造成内存泄漏

切记:动态开辟的空间一定要释放,并且正确释放

 

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

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

相关文章

查看自己电脑是arm还是x64(x86);linux操作系统识别

1、查看自己电脑是arm还是x64&#xff08;x86&#xff09; linux 参考&#xff1a; https://liuweiqing.blog.csdn.net/article/details/131783851 uname -a如果输出是 x86_64&#xff0c;那么你的系统是 64 位的 x86 架构&#xff08;通常我们称之为 x64&#xff09;。如果…

2023高精地图甲级测绘资质最新名单【高德地图】

根据2023年自然资源部公布的名单显示&#xff0c;以下公司通过“地图甲级测绘资质”换证审核&#xff0c;也就意味着&#xff0c;以下这些公司可以继续从事电子地图的采集和制作、商业合作等相关业务。 而这一点&#xff0c;对于以电子地图导航为主要业务支撑的企业至关重要。…

创建TextMeshPro字体文件

相比于Unity的Text组件&#xff0c;TextMesh Pro提供了更强大的文本格式和布局控制&#xff0c;更高级的文本渲染技术&#xff0c;更灵活的文本样式和纹理支持&#xff0c;更好的性能以及更易于使用的优点。但unity自带TextMeshPro字体不支持中文。这里使用普通字体文件生成Tex…

Spring事件之注解@EventListener讲解

文章目录 1 注解EventListener1.1 示例Demo1.1.1 简单例子1.1.2 解耦1.1.3 Spring事件 1.2 深入EventListener1.2.1 debug调试1.2.2 问题一&#xff1a; Spring是怎么知道要去触发这个方法1.2.3 问题二&#xff1a;ApplicationListenerMethodAdapter1.2.4 问题三&#xff1a;Si…

(12)喝汽水

文章目录 每日一言题目解题思路一代码 解题思路二代码 结语 每日一言 长风沛雨&#xff0c;艳阳明月。田野被喜悦铺满&#xff0c;天地间充满着生的豪情。 题目 已知1瓶汽水1元&#xff0c;2个空瓶可以换一瓶汽水&#xff0c;输入整数n&#xff08;n>0&#xff09;&#x…

Maven工程的配置及使用

一、Maven章节 Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具 1.1、maven的作用 1&#xff09;依赖管理&#xff1a; 方便快捷的管理项目依赖的资源包&#xff08;jar包&#xff09;避免版本冲突 2&#xff09;统一项目结构&…

Android studio打开md无法显示md渲染问题

Where is Android Studio Markdown support plugin preview preference? - Stack Overflow android studio开发无法选择markdown渲染功能的问题 原因是java runtime出了问题 搜索下面功能 Choose Boot Java Runtime for the IDE 选择带JCEF的 可以选最新的java版本 重启之…

Jvm FullGC 如何排查?

使用场景 我们在使用系统时&#xff0c;有时请求和响应会变得特别慢&#xff0c;系统也变得很卡。 有可能是FullGC的问题&#xff0c;可以逐步地进行排查。 使用jps和top确定进程号pid jps可以列出正在运行的jvm进程&#xff0c;并显示jvm执行主类名称( main()函数所在的类…

浙政钉(专有钉钉)

专有钉钉是浙政钉的测试版本&#xff0c;可在正式发布之前进行业务开发。 专有钉钉 原名政务钉钉 是高安全、强管控、灵活开放的面向大型组织专有独享的协同办公平台。支持专有云、混合云等多种方式灵活部署&#xff0c;以满足客户特定场景所需为目标&#xff0c;最大化以“平…

window 镜像---负载篇

前提&#xff1a;需要修改window的powershell执行脚本的策略 步骤&#xff1a;以管理员身份打开powershell&#xff0c;执行 Get-ExecutionPolicy查看当前执行策略&#xff0c;若返回值是Restricted&#xff0c;需执行Set-ExecutionPolicy RemoteSigned powershell 版本信息&am…

gif格式图片是怎么做的?教你一招在线转换

常见的图片有jpg、png以及gif格式&#xff0c;其中&#xff0c;jpg和png格式的图片我们一般手机拍摄或是接受的都是这两种格式&#xff0c;但是gif格式的图片我们却需要从网上下载。那么&#xff0c;当我们想要自己制作gif动画的时候要怎么操作呢&#xff1f;只需要使用在线制作…

MAE实战:使用MAE提高主干网络的精度(一)

摘要 MAE已经出来有几年了&#xff0c;很多人还不知道怎么去使用&#xff0c;本文通过两个例子说明一下。分两部分&#xff0c;一部分介绍一个简单的例子&#xff0c;让大家了解MAE训练的流程。一部分是一个新的模型&#xff0c;让大家了解如何将自己的模型加入MAE。 论文标…

steam搬砖项目赚钱吗?操作流程看这一篇就够了

很多人应该听说过steam&#xff0c;它是国外一款知名的游戏社交平台&#xff0c;也是目前世界上最大的游戏平台之一。而steam搬砖项目&#xff0c;关键就是靠信息差。我们要做的就是在steam以低价买入道具装备&#xff0c;然后上架到网易buff卖出&#xff0c;赚取差价。 什么人…

【PLC一体机】PLC一体机中如何实现触摸屏和PC电脑的通讯

博主今天准备把之前买的PLC一体机拿出来玩一下&#xff0c;翻看以前的博文&#xff0c;发现没有记录分享PLC一体机中如何实现触摸屏程序下载的内容。 如之前博文介绍的那样&#xff0c;PLC一体机由PLC和触摸屏两部分集成的设备&#xff0c;因此设备内部已经做好了PLC和触摸屏之…

C++拷贝构造函数、赋值运算符重载

1.拷贝构造函数 拷贝构造函数的写法如图所示 调用方式如下 接下来我来说说它的特征 1.1特征 拷贝构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存在的类类型对象创建新对象时由编译器自动调用。 拷贝构造函…

XGB-2: Boosted Trees(提升树)简介

XGBoost代表“Extreme Gradient Boosting”&#xff0c;其中术语“Gradient Boosting”来源于Friedman的论文《Greedy Function Approximation: A Gradient Boosting Machine》。 梯度提升树已经存在一段时间&#xff0c;关于这个主题有很多资料。本部分将使用监督学习的元素&…

【Chrono Engine学习总结】1-安装配置与程序运行

本文仅用于个人安装记录。 官方安装教程 https://api.projectchrono.org/8.0.0/tutorial_install_chrono.html Windows下安装 windows下安装就按照教程好了。采用cmake-gui进行配置&#xff0c;建议首次安装只安装核心模块。然后依此configure下irrlicht&#xff0c;sensor…

6款超好用的IDEA插件,开发必备!

今天给大家介绍几款开发必备的IDEA插件&#xff1a; JRebel 热部署插件&#xff0c;让你在修改完代码后&#xff0c;不用再重新启动&#xff0c;很实用&#xff01;但是&#xff0c;不是免费的&#xff0c;需要大家继续发挥下自己的聪明才智才能happy的使用 Json Parser 厌倦…

Abp 从空白的WebApplication中添加EntityFrameworkCore生成数据库

书接上文&#xff1a;Abp 从空白WebApplication开始 开发环境&#xff1a;.NET6、Volo.Abp 数据库&#xff1a;Sqlite 说明&#xff1a;纯属个人强行入门。我个人觉得按照官网的操作不舒服&#xff0c;所以自己研究着来&#xff0c;请读者根据自己的需要进行参考。我能保证的…

Ubuntu+GPU搭建Stable-Diffusion教程

【前序】已经安装anaconda 1.git拉取项目到本地 执行git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git 进入项目目录下 cd stable-diffusion-webui/ 2. 安装对应Python依赖包 首先安装pytorch和torchvision&#xff0c;若是GPU环境的用户需要安装与cu…