C语言 — 动态内存管理(动态内存函数)
前言
本期分为三篇介绍动态内存管理相关内容,关注博主了解更多
博主博客链接:https://blog.csdn.net/m0_74014525
本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C++程序的内存开辟区域
系列文章
第一篇:C语言 — 动态内存管理(动态内存函数)
第二篇:C语言 — 常见的动态内存错误
第三篇:C语言 — 柔性数组
文章目录
- 前言
- 系列文章
- 一、动态内存分配是什么
- 二、为什么存在动态内存分配
- 三、动态内存函数的介绍
- 1. malloc
- 2. free
- 3. calloc
- 4. realloc
- 四、C/C++程序的内存开辟
- 1. 内存分配区域
- 总结
一、动态内存分配是什么
动态内存分配是指在程序运行期间由程序自己向操作系统请求分配一定大小的内存空间,以存储程序运行时所需的数据。 由于动态分配的内存空间在程序运行期间是可变的,所以它比静态分配更加灵活。
动态内存分配带来的好处是可以根据实际需要动态调整内存大小,从而避免浪费内存。 但是,如果程序员不小心管理动态分配的内存,就可能会导致内存泄漏或者内存溢出等问题,严重影响程序的性能和稳定性。因此,使用动态内存分配时需要注意内存的释放和管理。
常见的动态内存分配函数有 malloc、calloc、realloc 等。其中 malloc 分配指定大小的内存块,calloc 分配并初始化一定数量的内存块,realloc 可以重新调整已分配的内存块的大小。
二、为什么存在动态内存分配
我们已经掌握的内存开辟方式有:
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点:
- 空间开辟大小是固定的。
- 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。
有时候我们需要的空间大小在程序运行的时候才能知道,
那数组的编译时开辟空间的方式就不能满足了。
这时候就只能试试动态存开辟了。
三、动态内存函数的介绍
1. malloc
malloc函数在C语言中用于在程序运行时向内存申请一块指定大小的内存空间。
函数格式:
void* malloc (size_t size);
其中,size_t是一个无符号整数类型,用于表示申请内存的字节数。malloc函数返回一个void指针,指向分配的内存空间的起始地址。如果分配失败,malloc函数返回空指针NULL。
函数特点:
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
- 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
使用malloc函数申请内存时,需要注意以下几点:
| 1. | 申请的内存大小应该是变量或数据类型的字节数乘以需要存储或操作的元素个数,以保证申请到足够的内存空间。 |
| 2. | 申请到的内存空间必须使用free函数进行释放,否则会导致内存泄露。 |
| 3. | 申请到的内存空间不会被自动初始化,即其中的数据是随机的,需要手动进行初始化。 |
举例演示:
#include <stdio.h>
#include <stdlib.h>int main() {int *p;p = (int*)malloc(10*sizeof(int)); //申请10个int类型数据的内存空间if (p == NULL) { //判断申请是否成功printf("Memory allocation failed.");exit(1);}for (int i = 0; i < 10; i++) { //手动初始化数据*(p+i) = i;}for (int i = 0; i < 10; i++) { //输出数据printf("%d\t", *(p+i));}free(p); //释放内存空间p=NULL; //将指针置为空return 0;
}
2. free
free 函数是 C 语言中用来释放动态分配的内存的函数
函数格式:
void free (void* ptr);
其中,ptr 是之前调用 malloc、calloc 或 realloc函数返回的指针。调用 free 函数后,指针所指向的内存将会被操作系统回收,可以再次被分配给其他程序使用。
函数特点:
- 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
使用 free 函数的时候需要注意以下几点:
| 1. | 只能释放动态分配的内存,不能释放栈或全局变量中的内存。 |
| 2. | 如果多次释放同一个指针,会导致程序异常。 |
| 3. | 如果指针为空指针(NULL),则不会进行任何操作。 |
3. calloc
calloc函数是C语言中的一个内存分配函数,用于在内存中分配指定大小的连续空间,并将其中的每个字节都初始化为0。
函数格式:
void* calloc (size_t num, size_t size);
其中,num表示要分配的元素数量,size表示每个元素的大小。函数返回一个指向新分配内存的指针,如果分配失败则返回NULL。
函数特点:
- 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
- 与malloc函数不同,calloc函数在分配内存时会自动清空分配的内存空间,所以一般用于需要初始化内存的情况。但它的缺点是比malloc函数慢,因为它需要在分配内存时进行清空操作。
使用calloc函数申请内存时,需要注意以下几点:
| 1. | 申请的内存大小应该是变量或数据类型的字节数乘以需要存储或操作的元素个数,以保证申请到足够的内存空间。 |
| 2. | 申请到的内存空间必须使用free函数进行释放,否则会导致内存泄露。 |
| 3. | 申请到的内存空间不会被自动初始化,即其中的数据是随机的,需要手动进行初始化。 |
| 4. | 区别于malloc,calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 |
举例演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{int* p = (int*)calloc(10, sizeof(int));if (NULL != p){//使用空间}free(p);p = NULL;return 0;
}

如何对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务
4. realloc
realloc函数是C语言中的一个库函数,用于重新分配动态分配的内存空间。
1.用于调整现有的内存块大小、
2.分配新的内存块
3.用于释放现有的内存块,当传递给它一个空指针时。
函数格式:
void* realloc(void* ptr, size_t size);
ptr表示指向已经动态分配的内存块的指针。
size表示需要重新分配的内存块的新尺寸。
返回值:如果分配失败,则返回NULL指针;否则返回一个新的指针,指向重新分配后的内存块。
函数特点:
使用realloc函数申请内存时,需要注意以下几点:
| 1. | 如果新的尺寸大于旧的尺寸,realloc函数将在原来的内存块后面分配额外的内存,使其达到新的尺寸。 |
| 2. | 如果新的尺寸小于旧的尺寸,realloc函数将会释放一部分内存,使其达到新的尺寸。 |
| 3. | 如果ptr是空指针,则等同于调用malloc函数。如果size是0,等同于调用free函数。 |
realloc在调整内存空间的是存在两种情况:
- 情况1:原有空间之后有足够大的空间
- 情况2:原有空间之后没有足够大的空间

情况1:
当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2:
当是情况2 的时候,原有空间之后没有足够多的空间时,
扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
由于上述的两种情况,realloc函数的使用就要注意一些。
四、C/C++程序的内存开辟

1. 内存分配区域
C/C++程序内存分配的几个区域:
| 栈区(stack) | 在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。 |
| 堆区(heap) | 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。 |
| 数据段 (静态区)(static) | 存放全局变量、静态数据。程序结束后由系统释放。 |
| 代码段 | 存放函数体(类成员函数和全局函数)的二进制代码。 |
总结
本期博客的重要点概况:
malloc函数:用于动态内存的开辟
calloc函数:也是用于动态内存开辟,区别于malloc,calloc函数会将每一个字节初始化为0
realloc函数:用于扩展内存空间,需要注意增加内存的返回,分为情况1和2
free函数:用于释放动态内存空间
如这篇博客对大家有帮助的话,希望 三连 支持一下 !!! 如果有错误感谢大佬的斧正 如有 其他见解发到评论区,一起学习 一起进步。
相关文章:
C语言 — 动态内存管理(动态内存函数)
前言 本期分为三篇介绍动态内存管理相关内容,关注博主了解更多 博主博客链接:https://blog.csdn.net/m0_74014525 本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C程序的内存开辟区域 系列文章 第一篇ÿ…...
Visual ChatGPT:Microsoft ChatGPT 和 VFM 相结合
推荐:使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Visual ChatGPT? Visual ChatGPT 是一个包含 Visual Foundation 模型 (VFM) 的系统,可帮助 ChatGPT 更好地理解、生成和编辑视觉信息。VFM 能够指…...
基于java理发店预约系统微信小程序设计与实现
摘要 多姿多彩的世界带来了美好的生活,行业的发展也是形形色色的离不开技术的发展。作为时代进步的发展方面,信息技术至始至终都是成就行业发展的重要秘密。不论何种行业,大到国家、企业,小到团体、个人都在多方位的结合信息化技术…...
【软件测试】大厂测工都是这样学习的,你get到了吗?
有不少的软件测试工程师站在“十字路口”迷茫、无助,找不到自己的方向。一切的迷茫都是因为想得太多而做的太少!每位软件测试行业从业者都能意识到目前自己面临的窘境,但能及时作出改变,顺应时代变化的人还是太少。多数人明明“泰…...
如何使用ONLYOFFICE+ffmpeg来给视频文件打马赛克
如何使用ONLYOFFICEffmpeg来给视频文件打马赛克 我这里之前写过很多关于ONLYOFFICE使用、安装的系列图文,也写过很多关于ffmpeg使用的图文,那么这次继续,把这两个开源软件放在一起,能碰撞出什么火花般的功能来。 这就是给视频文…...
003-依赖注入、属性赋值源码分析
目录 引入作用代码分析InstantiationAwareBeanPostProcessor#postProcessProperties()AutowiredAnnotationBeanPostProcessor查找注入点元数据给注入点注入属性 引入 之前我们了解到BeanDefinition到Bean,经历了 实例化属性赋值初始化 3个步骤现在详细分析下属性赋…...
Elasticsearch 商业启示
上月的“红帽事件”,说明开源软件的“客服模式”行不通,那么,开源软件如何赚钱呢?既不能卖软件,又不能卖支持服务,该怎么办呢?我现在的看法是,只剩下一种模式是可行的,开…...
C++/Qt 读写文件
之前写过两篇跟文件操作相关的博客,有兴趣也可以看一下: C语言读写文件 Qt关于文件路径的处理 先讲一些关于基础文本文件和二进制文件的读写操作,后续将会整理C/Qt关于ini、xml、json、xlsx相关文件的读写操作。 C 相比于C语言使用FILE文…...
linux服务器之-nethogs命令
文章目录 NetHogs 工具安装安装依赖包安装epel源安装Nethogs 使用 NetHogs 工具 NetHogs是一个小型的net top工具,不像大多数工具那样拖慢每个协议或者是每个子网的速度而是依照进程进行带宽分组。 安装 安装依赖包 yum install libpcap libpcap-devel epel-rel…...
《每天5分钟玩转kubernetes》读书笔记
笔记 概念 Pod是脆弱的,但应用是健壮的。 kubelet运行在Cluster所有节点上,负责启动Pod和容器。kubeadm用于初始化Cluster。kubectl是k8s命令行工具。通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。 …...
【RabbitMQ】golang客户端教程4——路由(使用direct交换器)
路由 在上一教程中,我们构建了一个简单的日志记录系统。我们能够向许多接收者广播日志消息。 在本教程中,我们将向它添加一个特性-我们将使它能够只订阅消息的一个子集。例如,我们将只能将关键错误消息定向到日志文件(以节省磁盘…...
Shell脚本学习-for循环结构2
案例:通过脚本实现仅sshd、rsyslog、crond、network、sysstat服务在开机时自启动。 Linux系统在开机的服务通常工作在文本模式3级别,因此只需要查找3级别以上的开启的服务即可。查看命令: chkconfig --list |grep 3:on [rootvm1 ~]# chkco…...
vue 老项目 npm install 报错Python,c++等相关错误
老项目npm install 下载依赖包报错 解决方法: //下载python 1、 npm install --global --production windows-build-tools//配置环境 : 也可暂时不用配置,能用就不用配置(npm config set python "D:\Python27\python.exe&q…...
【c语言初级】c++基础
文章目录 1. C关键字2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.2 C函数重载的原理--名字修饰采用C语言编译器编译后结果 1. C关键字 C是在C的基础之上,容纳进去了面向对象编程思想…...
idea打开传统eclipse项目
打开传统web项目 1.打开后选择项目文件 2.选择项目结构 3.设置jdk版本 4.导入当前项目模块 5.选择eclipse 6. 设置保存目录 7.右键模块,添加spring和web文件 8. 设置web目录之类的,并且创建打包工具 9.如果有本地lib,添加为库 最后点击应用&…...
全国各城市-财政收入-一般预算收入-各项税收-个人所得税(1999-2020年)
个人所得税是一项反映国家财政状况和个人经济水平的重要数据。通过对全国各城市个人所得税数据的研究,可以提供研究者参考的有益信息。首先,个人所得税数据反映了不同城市居民的收入水平。通过对不同城市的个人所得税数据进行比较,可以了解不…...
【动态网页抓取】 :用Python抓取所有内容的指南
一、说明 您在抓取动态网页内容时是否得到了糟糕的结果?不仅仅是你。对于标准抓取工具来说,爬网动态数据是一项具有挑战性的任务(至少可以说)。这是因为当发出HTTP请求时,响应程序的某些部分JavaScript在后台运行&…...
Spring Boot数据访问基础知识与JDBC简单实现
目录 Spring Boot数据访问基础知识 Spring Data ORM JDBC JPA JDBC简单实现 步骤1:新建Maven项目,添加依赖 步骤2:配置数据源—让程序可以访问到 步骤3:配置数据源—让IDEA可以访问到 步骤4:添加数据库和表 …...
ubuntu添加万能头文件
ubuntu的C头文件目录为/usr/include 在/usr/include下新建文件夹 bits sudo mkdir bits进入bits,新建stdc.h,并修改权限为744/777 cd bits;sudo touch stdc.h;sudo chmod 777 stdc.h将以下内容粘贴到stdc.h,保存退出 // C includes used …...
聊一聊关于前端语法 ?? 的那些事
当我们在编写前端代码时,语法是非常重要的。正确的语法可以确保我们的代码能够正常运行,并且易于维护和理解。在本文中,我们将探讨一些前端语法的问题,例如空值合并运算符(??)。 空值合并运算符是ES2020…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
