C 学习笔记 —— 动态分配内存(malloc)
文章目录
- 分配内存
- malloc
- calloc
- realloc
- 创建数组方式
- free的重要性
- 举例
- 常见动态分配内存错误
- 忘记检查所请求的内存
- 对NULL指针进行解引用
- 对分配的内存越界访问
- 释放一块内存后,继续使用
- 释放一块内存的一部分是不允许的
- 内存泄漏
分配内存
当一个数组声明时,需要指定数组大小,这个内存空间在编译的时候就已经被分配了。
但是如果我们要使用一个数组,我们事先并不知道他的大小,而想在运行时计算出来,那么也可以在程序运行时动态分配内存。
上面的内存分配与回收都是系统帮我们做了,而我们不用管。如果我们想自己更灵活的分配和回收内存可以使用malloc和free。
需要引入#include <stdlib.h>库头文件,内存分配函数在这里面。
malloc
void * malloc(size_t size);
给malloc一个参数,表示要申请的内存大小,所需的byte数。
malloc会在内存池中找到一块空闲(连续)内存,返回内存块的首字节地址,所以可以把该地址赋值给一个指针,后面可以使用该指针访问这块内存。
这块内存通常比malloc申请的大一些,因为要存储一些信息。
如果malloc分配内存失败,则他会返回一个空指针 NULL,我们可以通过是否为空指针来判断是否成功分配了内存,这个很重要。
返回值类型是一个void类型的指针,该类型相当于一个通用指针,该指针通常被强转为一个匹配的类型并不需要考虑类型不匹配的问题,并且我们应该坚持这样做来保证代码的可读性,C中虽然不要求强制转换,但是C++中必须使用,那么我们坚持这样做来保证可移植性。
double *pt = (double *) malloc (30 * sizeof(double));
这段代码为30个double类型的值申请了一块内存,并设置pt指向该内存首元素地址。
回忆一下,数组名为该数组的首元素地址。所以pt指向该块内存的首元素,那么我们可以用数组名来使用它。可以使用数组名来表示指针,也可以使用指针来表示数组名。
我们可以使用pt[0]来访问该块的首元素,pt[1]来访问第二个元素。
calloc
函数原型
void * calloc(size_t num_elements, size_t element_size);
calloc函数
long* num;
num = (long *)calloc(100, sizeof(long));
calloc第一个参数是存储单元数量,第二个参数是存储单元大小。
他的返回值也是void* 需要强转成需要的类型。
他还有一个特性是会把分配后的所有值都初始化为0. malloc不保证这一点,他的内存值并没有初始化为0。
realloc
void *realloc(void *ptr, size_t new_size);
realloc函数用于修改一个原先已经分配的内存块的大小。
使用这个函数可以让一个内存扩大或者缩小。
如果扩大内存,则原内容保留,扩大到内存部分并不保证数据的初始化。
如果缩小内存,则改内存尾部部分会被删掉 ,剩余内存保留原县内容。
操作系统中可能原内存块无法改变大小,这是操作系统会分配一块新内存出来,新内存遵循上面两个规则,并将新指针返回。
如果realloc的第一个参数为NULL,则他的行为和malloc函数一摸一样。
创建数组方式
所以现在我们有两种方式创建数组
第一种:直接创建double item[30];
第二种:动态创建
int n = 6;
double *pt = (double *) malloc(n * sizeof(double));
第一种我们必须指定一个常量作为数组的大小。
而第二种的优势是我们可以创建一个变长数组。
使用malloc在运行时才确定内存数组的大小。
使用的时候,我们不仅可以使用指针,还可以使用下标来访问内存,如下例子:
#include <stdio.h>
#include <stdlib.h> /* for malloc(), free() */int main(void)
{double * ptd;int max;int number;int i = 0;max = 6;ptd = (double *) malloc(max * sizeof (double)); //分配动态数组if (ptd == NULL) //如果分配失败则退出{puts("Memory allocation failed. Goodbye.");exit(EXIT_FAILURE);//异常退出程序}/* ptd now points to an array of max elements */puts("Enter the values (q to quit):");while (i < max && scanf("%lf", &ptd[i]) == 1)++i;printf("Here are your %d entries:\n", number = i);for (i = 0; i < number; i++){printf("%7.2f ", ptd[i]); //使用指针也即数组名访问元素if (i % 7 == 6)putchar('\n');}if (i % 7 != 0)putchar('\n');puts("Done.");free(ptd);//释放内存return 0;
}
free的重要性
我们使用free函数来释放malloc分配的内存,free接受参数为malloc返回的指针。
free的参数要么是NULL,要么是malloc,calloc,realloc返回的值。
当不断分配内存而忘记释放,可能会耗尽内存,这类问题称为内存泄漏。
举例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int static_store = 30;
const char * pcg = "String Literal";
int main()
{int auto_store = 40;char auto_string[] = "Auto char Array";int * pi;char * pcl;pi = (int *) malloc(sizeof(int));*pi = 35;pcl = (char *) malloc(strlen("Dynamic String") + 1);strcpy(pcl, "Dynamic String");printf("static_store: %d at %p\n", static_store, &static_store);printf(" auto_store: %d at %p\n", auto_store, &auto_store);printf(" *pi: %d at %p\n", *pi, pi);printf(" %s at %p\n", pcg, pcg);printf(" %s at %p\n", auto_string, auto_string);printf(" %s at %p\n", pcl, pcl);printf(" %s at %p\n", "Quoted String", "Quoted String");free(pi);free(pcl);return 0;
}
// static_store: 30 at 0x601048 静态区域
// auto_store: 40 at 0x7fff5f25f8dc 自动区域
// *pi: 35 at 0xeea010 堆
// String Literal at 0x4007a0 静态区域
// Auto char Array at 0x7fff5f25f8c0 自动区域
// Dynamic String at 0xeea030 堆
// Quoted String at 0x40080e 静态区域
常见动态分配内存错误
忘记检查所请求的内存
对NULL指针进行解引用
对分配的内存越界访问
如果我们通过数组下标访问了arr[-1]或者arr[11],那么arr[-1]是向前越界了,arr[11]是向后越界了。一般越界是越到变量分配的内存区域的后面区域,很少越界到当前访问的变量内存前面去的。有人可能会说,怎么可能会越界到负的下标(arr[-1])上去了呢?我们还真遇到过,后面我们给大家专门讲一个向前越界的实例。
释放一块内存后,继续使用
释放一块内存的一部分是不允许的
free(pi+5)
内存泄漏
相关文章:
C 学习笔记 —— 动态分配内存(malloc)
文章目录分配内存malloccallocrealloc创建数组方式free的重要性举例常见动态分配内存错误忘记检查所请求的内存对NULL指针进行解引用对分配的内存越界访问释放一块内存后,继续使用释放一块内存的一部分是不允许的内存泄漏分配内存 当一个数组声明时,需要…...
RK3588通用布线设计指南
(1)走线长度应包含过孔和封装。(2)由于表贴器件的焊盘会导致阻抗降低,为减小阻抗突变的影响,建议在表贴焊盘的正下方按焊盘大小挖去一层参考层。常用的表贴器件有:电容、 ESD、共模抑制电感、连…...
ChatGPT也懂如何设计开发板!?
到底应该如何设计一款开发板?我们问了一下最近风很大的ChatGPT,得出了这样的回答: 或者这样的回答: 显而易见,RK3568开发板是一款功能丰富,性能优异,易于开发的高性能开发板,适用于各…...
去了字节跳动,才知道年薪40W的测试居然有这么多?
今年大环境不好,内卷的厉害,薪资待遇好的工作机会更是难得。最近脉脉职言区有一条讨论火了: 哪家互联网公司薪资最‘厉害’? 下面的评论多为字节跳动,还炸出了很多年薪40W的测试工程师 我只想问一句,现在的…...
2023前端面试知识点总结
原型 JavaScript中的对象都有一个特殊的 prototype 内置属性,其实就是对其他对象的引用 几乎所有的对象在创建时 prototype 属性都会被赋予一个非空的值,我们可以把这个属性当作一个备用的仓库 当试图引用对象的属性时会出发get操作,第一步时…...
FL StudioV21电脑版水果编曲音乐编辑软件
这是一款功能十分丰富和强大的音乐编辑软件,能够帮助用户进行编曲、剪辑、录音、混音等操作,让用户能够全面地调整音频。FL水果最新版是一款专业级别的音乐编曲软件,集合更多的编曲功能为一身,可以进行录音、编辑、制作、混音、调…...
【数据结构初阶】实现顺序表的简单功能
目录一.线性表和顺序表的概念二.顺序表的实现1.动态顺序表的创建2.初始化顺序表3.打印顺序表4.销毁顺序表5.检查容量6.头插 尾插7.头删 尾删三.使用下标插入删除1.删除指定位置2.向指定位置插入指定数一.线性表和顺序表的概念 线性表是n个具有相同特性的数据元素的有限序列。 线…...
华为OD机试题,用 Java 解【停车场车辆统计】问题
最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…...
Linux中使用Docker部署Mysql数据库
前言 和朋友一起搞一个项目,分了一下工作,但是mysql迟迟安装不上,程序都在一个环境里确实容易出现很多问题,浪费时间和经历在这些配置上,好在有docker了,就在docker里搭建一个Mysql数据库使用吧࿰…...
JPDA(远程调试)使用步骤
JPDA(Java Plateform Debugger Architecture) 更改启动脚本 vi catalina.sh 127行 CATALINA_OPTS “-Xdebug -Xrunjdwp:transportdt_socket,servery,suspendn,address5888” 指定端口,默认是8000 377行以jpda方式启动tomcat ./catalina.sh jpda start tomcat以这个…...
磷脂-聚乙二醇-丙烯酸酯;DSPE-PEG-AC试剂说明;DSPE-PEG-Acrylate科研用
中文名称:磷脂-聚乙二醇-丙烯酸酯 丙烯酸酯-聚乙二醇-磷脂 简称:DSPE-PEG-AC;DSPE-PEG-Acrylate 溶剂:溶于部分常规有机溶剂 PEG分子量:1000;2000;3400;5000等等 注意事项:避免…...
C++入门:异常处理
异常是程序在执行期间产生的问题。C 异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。异常提供了一种转移程序控制权的方式。C 异常处理涉及到三个关键字:try、catch、throw。throw: 当问题出现时,程序会抛出一个异常。这是通过使…...
C/C++每日一练(20230225)
目录 1. 工龄问题求解 ★ 2. 字符图形输出 ★★ 3. LRU 缓存机制 ★★★ 1. 工龄问题求解 给定公司N名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。输入首先给出正整数N,即员工总人数; 随后给出N个整数,即每个员工…...
nyist最终淘汰赛第一场
我出的题喜欢吗 我要水题解所以每一篇题解都分一个博客 A 题解链接: Atcoder abc257 E_霾まる的博客-CSDN博客 构造贪心题 在本次淘汰赛中较难 B 题解链接: atcoder abc217 D_霾まる的博客-CSDN博客 STL二分题, 当然你可以数组二分, 相对麻烦一点 在本次淘汰赛中较简单…...
《零成本实现Web自动化测试--基于Selenium》 Selenium-RC
一. 简介 Selenium-RC可以适应更复杂的自动化测试需求,而不仅仅是简单的浏览器操作和线性执行。Selenium-RC能够充分利用编程语言来构建更复杂的自动化测试案例,例如读写文件、查询数据库和E-mail邮寄测试报告。 当测试案例遇到selenium-IDE不支持的逻辑…...
来阿里我的收获是什么?(未完待续)
不知不觉来阿里两年多了,每天都过的很充实,感觉这段时间没有学到什么东西,但是又觉得收获满满,恰好又好久没有动笔写过些什么了,所以有了这个动笔念头。 之前技术方面记录的比较多,这次就记录一些比较磨心的…...
golang net/http库的学习
net/http 是 Golang 标准库中用来构建 HTTP 服务器和客户端的包,它提供了很多功能强大的方法和接口,可以让您方便地构建和处理 HTTP 请求和响应。下面是一些学习 net/http 的建议: 了解 HTTP 协议。在学习 net/http 之前,建议先了…...
Spring(AOP)
目录 1. 预备知识-动态代理 1.1 什么是动态代理1.2 动态代理的优势1.3 基于JDK动态代理实现2. AOP 2.1 基本概念2.2 AOP带来的好处3. Spring AOP 3.1 前置通知3.2 后置通知3.3 环绕通知3.4 异常通知3.5 适配器 1. 预备知识-动态代理 1.1 什么是动态代理 动态代理利用Java的反…...
服务搭建篇(六) Kafka + Zookeeper集群搭建
一.Zookeeper 1.什么是Zookeeper ZooKeeper 是一个开源的分布式协调框架,是Apache Hadoop 的一个子项目,主要 用来解决分布式集群中应用系统的一致性问题。Zookeeper 的设计目标是将那些复杂且容 易出错的分布式一致性服务封装起来,构成一个…...
Go基础-可变参数函数
文章目录1 定义2 语法3 给可变函数参数传入切片4 修改可变参数函数中的切片1 定义 可变参数函数是一种参数个数可变的函数。 2 语法 语法 //关键字 函数名(参数1, elems为T类型的可变参数) 返回值类型 func name(params type, elems ...T) returntype{// 函数体 }…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析
LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...
以太网PHY布局布线指南
1. 简介 对于以太网布局布线遵循以下准则很重要,因为这将有助于减少信号发射,最大程度地减少噪声,确保器件作用,最大程度地减少泄漏并提高信号质量。 2. PHY设计准则 2.1 DRC错误检查 首先检查DRC规则是否设置正确,然…...
uni-app学习笔记二十七--设置底部菜单TabBar的样式
官方文档地址:uni.setTabBarItem(OBJECT) | uni-app官网 uni.setTabBarItem(OBJECT) 动态设置 tabBar 某一项的内容,通常写在项目的App.vue的onLaunch方法中,用于项目启动时立即执行 重要参数: indexnumber是tabBar 的哪一项&…...
