【C语言】内存管理
【C语言】内存管理
文章目录
- 【C语言】内存管理
- 1.概念
- 2.库函数
- 3.动态分配内存
- malloc
- calloc
- 4.重新调整内存的大小和释放内存
- realloc
- free
1.概念
C 语言为内存的分配和管理提供了几个函数。这些函数可以在 <stdlib.h> 头文件中找到。
在 C 语言中,内存是通过指针变量来管理的。指针是一个变量,它存储了一个内存地址,这个内存地址可以指向任何数据类型的变量,包括整数、浮点数、字符和数组等。C 语言提供了一些函数和运算符,使得程序员可以对内存进行操作,包括分配、释放、移动和复制等。
2.库函数
序号 | 函数及描述 |
---|---|
1 | void *calloc(int num, int size); 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为0。所以它的结果是分配了 num * size 个字节长度的内存空间,并且每个字节的值都是0。 |
2 | void free(void *address); 该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。 |
3 | void *malloc(int num); 在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。 |
4 | void *realloc(void *address, int newsize); 该函数重新分配内存,把内存扩展到 newsize 。 |
**注意:**void * 类型表示未确定类型的指针。C、C++ 规定 void * 类型可以通过类型转换强制转换为任何其它类型的指针。
3.动态分配内存
编程时,如果预先知道数组的大小,那么定义数组时就比较容易。例如,一个存储人名的数组,它最多容纳 100 个字符,所以您可以定义数组,如下所示:
char name[100];
但是,如果预先不知道需要存储的文本长度,例如想存储有关一个主题的详细描述。在这里,我们需要定义一个指针,该指针指向未定义所需内存大小的字符,后续再根据需求来分配内存,如下所示:
malloc
void *malloc(size_t size);size 参数指定了需要分配的内存大小,单位是字节(byte)。size_t 是一个无符号整数类型,通常用来表示大小和计数。功能描述:
malloc 函数在程序的堆区(heap)请求一块至少为 size 字节的内存区域。如果内存分配成功,malloc 返回一个指向这块内存的指针,程序员可以使用这个指针来访问和操作分配的内存。
如果分配失败,通常是因为堆上没有足够的内存空间,malloc 会返回 NULL。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{char name[100];char *p;strcpy(name, "xiao ming");/* 动态分配内存 */p = (char *)malloc( 10 * sizeof(char) );// 分配一个整数数组的空间,大小为10个charif( p == NULL ){perror("malloc");}else{strcpy( p, "xiao ming is a student ");}printf("Name = %s\n", name );printf("p: %s\n", p );free(p);
}
注意事项:
- 初始化:
malloc
分配的内存空间不会被自动初始化,它的初始内容是未定义的。如果需要初始化,必须手动设置。 - 内存泄漏:使用
malloc
分配的内存必须在不再需要时使用free
函数释放。如果忘记释放,将导致内存泄漏。 - 大小计算:分配数组时,需要使用
sizeof
来确保分配的内存大小正确。例如,分配一个包含n
个元素的数组时,应使用n * sizeof(element)
作为malloc
的参数。 - 错误处理:如果
malloc
返回NULL
,应该妥善处理这种情况,可能是程序应该终止或采取其他恢复措施。 - 指针类型:
malloc
返回的是void*
类型的指针,这是C语言中所有指针类型的通用类型。在使用malloc
分配特定类型的内存时,通常需要强制类型转换,如int* array = malloc(10 * sizeof(int));
。
malloc
是动态内存分配的核心函数之一,在需要处理不确定数量的数据或实现某些数据结构(如链表、树等)时非常有用。正确使用 malloc
和 free
对于编写稳健和高效的C程序至关重要。
calloc
calloc
是 C 语言中用于动态内存分配的另一个标准库函数,它在很多方面与 malloc
相似,但有一个关键的区别在于初始化行为。下面是 calloc
函数的详细介绍:
函数原型:
void *calloc(size_t num, size_t size);
num
参数指定了要分配的元素数量。size
参数指定了每个元素的大小,单位是字节。
功能描述:
calloc
函数在程序的堆区分配一块总大小为num * size
字节的内存区域,并且将这块内存区域的每个字节都初始化为0。这使得calloc
成为分配和初始化静态数组或数据结构(如矩阵)的理想选择。- 如果内存分配成功,
calloc
返回一个指向这块内存的指针;如果失败,返回NULL
。
使用示例:
#include <stdlib.h> // 包含calloc函数的头文件int main() {int rows = 5;int columns = 5;// 分配一个5x5的整数矩阵,并初始化为0int *matrix = calloc(rows * columns, sizeof(int));if (matrix == NULL) {// 处理内存分配失败的情况fprintf(stderr, "Memory allocation failed.\n");return 1;}// 使用分配的内存// 注意:矩阵已经初始化为0free(matrix); // 释放分配的内存return 0;
}
注意事项:
- 初始化:与
malloc
不同,calloc
分配的内存区域会自动初始化为0,这对于需要清零的数据结构非常有用。 - 内存泄漏:和
malloc
一样,使用calloc
分配的内存也必须在使用完毕后用free
函数释放,以避免内存泄漏。 - 大小计算:分配数组或复合数据结构时,应使用
sizeof
来确保分配的内存大小正确。 - 错误处理:如果
calloc
返回NULL
,应该妥善处理这种情况,可能是程序应该进行错误恢复或终止。 - 指针类型:
calloc
返回的是void*
类型的指针,在使用时通常需要强制类型转换到具体的数据类型指针。
calloc
是动态内存分配中一个非常有用的函数,特别是当你需要分配一块内存并确保它是清零的状态时。正确地使用 calloc
可以帮助你更容易地初始化复杂的数据结构,并保持代码的清晰和简洁。
4.重新调整内存的大小和释放内存
当程序退出时,操作系统会自动释放所有分配给程序的内存,但是,建议在不需要内存时,都应该调用函数 free() 来释放内存。
或者,可以通过调用函数 realloc() 来增加或减少已分配的内存块的大小。让我们使用 realloc() 和 free() 函数。
realloc
realloc
是 C 语言中的一个用于内存管理的函数,它允许你更改先前使用 malloc
或 calloc
函数分配的内存块的大小。这个函数非常有用,当你需要调整一个数据结构的大小以适应程序运行时变化的需求时。
函数原型:
void *realloc(void *ptr, size_t new_size);
ptr
是指向先前分配的内存块的指针。new_size
是新的内存大小,单位是字节。
功能描述:
realloc
尝试将指针ptr
指向的内存块调整为new_size
字节大小。- 如果
ptr
是NULL
,realloc
表现得就像malloc(new_size)
,分配一个新的内存块。 - 如果
new_size
是 0,realloc
表现得就像free(ptr)
,释放内存块。 - 如果
realloc
成功,它返回指向重新分配(可能移动)内存块的指针。如果内存块被移动,原内存块的内容会被复制到新位置。 - 如果
realloc
失败,它返回NULL
,原始内存块保持不变。
使用示例:
#include <stdlib.h> // 包含realloc函数的头文件int main() {int *array = malloc(5 * sizeof(int)); // 初始分配if (array == NULL) {fprintf(stderr, "Initial memory allocation failed.\n");return 1;}// 假设需要扩大数组array = realloc(array, 10 * sizeof(int)); // 重新分配更大的空间if (array == NULL) {fprintf(stderr, "Memory reallocation failed.\n");free(array); // 确保释放原始内存return 1;}// 使用扩大后的数组// ...free(array); // 释放分配的内存return 0;
}
注意事项:
- 内存块可能移动:
realloc
可能会将内存块移动到堆中的另一个位置,因此返回的新指针可能与原始指针不同。这意味着你应该总是使用realloc
返回的指针来引用内存。 - 内容复制:如果内存块被移动,
realloc
会自动将原始内存块的内容复制到新位置。 - 内存泄漏风险:如果
realloc
失败,原始内存块仍然有效,不会自动释放。因此,你应该在重新分配内存之前保存原始指针的副本,并在必要时释放它。 - 错误处理:如果
realloc
返回NULL
,应该检查new_size
是否为预期值,并处理可能的错误情况。 - 性能考虑:频繁地使用
realloc
可能会导致性能问题,特别是如果内存块经常需要移动到新位置时。
realloc
是一个强大的工具,可以帮助你管理程序运行时的内存需求。然而,由于它可能会改变内存块的位置,使用时需要小心,确保正确地处理返回的新指针。
free
free
函数是 C 语言中用于释放之前使用 malloc
、calloc
或 realloc
函数分配的动态内存的标准库函数。正确地使用 free
函数对于防止内存泄漏和有效管理程序的内存使用至关重要。
函数原型:
void free(void *ptr);
ptr
是指向要释放的内存块的指针。如果ptr
是NULL
,调用free
没有效果,但这种调用是安全的,不会引发错误。
功能描述:
free
函数的作用是将之前动态分配的内存块返回给操作系统或运行时环境,使其可以被其他部分的程序再次使用。- 当没有更多的内存可用于新的内存分配请求时,释放不再需要的内存块是一种良好的编程实践。
注意事项:
- 释放NULL指针:根据 C 标准,尝试释放一个
NULL
指针是安全的,free
将不做任何操作。 - 悬挂指针:释放内存后,指针指向的内存已经不再属于你的程序,因此不应再使用该指针(称为悬挂指针)。
- 内存泄漏:如果忘记了调用
free
来释放动态分配的内存,将导致内存泄漏,长期运行的程序可能会因此耗尽可用内存。 - 重复释放:不应尝试多次释放同一块内存,这可能会导致未定义的行为或程序崩溃。
使用 free
函数是 C 语言编程中的一个重要方面,它确保了程序的健壮性和资源的有效使用。记住,每次使用 malloc
、calloc
或 realloc
分配内存时,都应该在适当的时候使用 free
来释放内存。
相关文章:
【C语言】内存管理
【C语言】内存管理 文章目录 【C语言】内存管理1.概念2.库函数3.动态分配内存malloccalloc 4.重新调整内存的大小和释放内存reallocfree 1.概念 C 语言为内存的分配和管理提供了几个函数。这些函数可以在 <stdlib.h> 头文件中找到。 在 C 语言中,内存是通过…...

deepseek大模型本机部署
2024年1月20日晚,中国DeepSeek发布了最新推理模型DeepSeek-R1,引发广泛关注。这款模型不仅在性能上与OpenAI的GPT-4相媲美,更以开源和创新训练方法,为AI发展带来了新的可能性。 本文讲解如何在本地部署deepseek r1模型。deepseek官…...
动态规划DP 最长上升子序列模型 拦截导弹(题目分析+C++完整代码)
概览检索 动态规划DP 最长上升子序列模型 拦截导弹 原题链接 AcWiing 1010. 拦截导弹 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每…...
缩位求和——蓝桥杯
1.题目描述 在电子计算机普及以前,人们经常用一个粗略的方法来验算四则运算是否正确。 比如:248153720248153720 把乘数和被乘数分别逐位求和,如果是多位数再逐位求和,直到是 1 位数,得 24814>145 156 56 而…...

Baklib赋能企业实现高效数字化内容管理提升竞争力
内容概要 在数字经济的浪潮下,企业面临着前所未有的机遇与挑战。随着信息技术的迅猛发展,各行业都在加速推进数字化转型,以保持竞争力。在这个过程中,数字化内容管理成为不可或缺的一环。高效的内容管理不仅能够优化内部流程&…...

【视频+图文讲解】HTML基础2-html骨架与基本语法
图文教程 基本骨架 举个例子,下图所展示的为html的源代码 -!DOCTYPE:表示文档类型(后边写的html表示文档类型是html);其中“!”表示声明 只要是加这个声明标签的,浏览器就会把下边的源代码当…...

消息队列篇--原理篇--常见消息队列总结(RabbitMQ,Kafka,ActiveMQ,RocketMQ,Pulsar)
1、RabbitMQ 特点: AMQP协议:RabbitMQ是基于AMQP(高级消息队列协议)构建的,支持多种消息传递模式,如发布/订阅、路由、RPC等。多语言支持:支持多种编程语言的客户端库,包括Java、P…...
【力扣每日一题】存在重复元素 II 解题思路
219. 存在重复元素 II 解题思路 问题描述 给定一个整数数组 nums 和一个整数 k,要求判断数组中是否存在两个 不同的索引 i 和 j,使得: nums[i] nums[j]且满足 abs(i - j) < k 如果满足上述条件,返回 true,否则…...
React第二十八章(css modules)
css modules 什么是 css modules 因为 React 没有Vue的Scoped,但是React又是SPA(单页面应用),所以需要一种方式来解决css的样式冲突问题,也就是把每个组件的样式做成单独的作用域,实现样式隔离,而css modules就是一种…...

本地运行大模型效果及配置展示
电脑上用ollama安装了qwen2.5:32b,deepseek-r1:32b,deepseek-r1:14b,llama3.1:8b四个模型,都是Q4_K_M量化版。 运行过程中主要是cpu和内存负载比较大,qwen2.5:32b大概需要22g,deepseek-r1:32b类…...
愿景:做机器视觉行业的颠覆者
一个愿景,两场战斗,专注制胜。 一个愿景:做机器视觉行业的颠覆者。 我给自己创业,立一个大的愿景:做机器视觉行业的颠覆者。 两场战斗:无监督-大模型 上半场,无监督。2025-2030,共五…...

arm-linux-gnueabihf安装
Linaro Releases windows下打开wsl2中的ubuntu,资源管理器中输入: \\wsl$gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz 复制到/home/ark01/tool 在 Ubuntu 中创建目录: /usr/local/arm,命令如下: …...

力扣动态规划-16【算法学习day.110】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?建议灵神的题单和代码随想录)和记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关…...
Java基础知识总结(三十四)--java.util.Date
月份从0-11; /* 日期对象和毫秒值之间的转换。 1,日期对象转成毫秒值。Date类中的getTime方法。 2,如何将获取到的毫秒值转成具体的日期呢? Date类中的setTime方法。也可以通过构造方法。 */ //日期对象转成毫秒值 Date …...
零售EDI:Costco EDI 项目须知
Costco 是全球领先的会员制仓储式零售商,致力于为会员提供高品质且价格实惠的商品。其经营范围涵盖食品、电子产品、家居用品、服装和办公设备等多个领域。 Costco 的 EDI 对接需求分析 为了更高效地管理其复杂的全球供应链,Costco 采用了先进的 EDI&am…...
最近最少使用算法(LRU最近最少使用)缓存替换算法
含义 最近最少使用算法(LRU)是一种缓存替换算法,用于在缓存空间有限的情况下,选择最少使用的数据项进行替换。该算法的核心思想是基于时间局部性原理,即刚被访问的数据在未来也很有可能被再次访问。 实现 LRU算法的…...
sublime_text的快捷键
sublime_text的快捷键 向下复制, 复制光标所在整行并插入到下一行:通过 CtrlShiftD 实现快速复制当前行的功能。 可选多行, 不选则复制当前行 ctrl Shift D 删除当前行:通过 CtrlShiftK 实现快速删除当前行的功能。 可选多行, 不选则删当前行 ctrl S…...

使用Pygame制作“贪吃蛇”游戏
贪吃蛇 是一款经典的休闲小游戏:玩家通过操控一条会不断变长的“蛇”在屏幕中移动,去吃随机出现的食物,同时要避免撞到墙壁或自己身体的其他部分。由于其逻辑相对简单,但可玩性和扩展性都不错,非常适合作为新手练习游戏…...

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操
本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操 Janus-Pro-7B介绍 Janus-Pro-7B 是由 DeepSeek 开发的多模态 AI 模型,它在理解和生成方面取得了显著的进步。这意味着它不仅可以处理文本,还可以处理图像等其他模态的信息。 模型主要特点:Permalink…...

Java开发vscode环境搭建
1 几个名词 JDK Java Development Kit JRE Java Runtion Environment JVM JDK 包括 Compiler,debugger,JRE等。JRE包括JVM和Runtime Library。 2 配置环境 2.1 安装JDK 类比 C/C的 g工具 官网:https://www.oracle.com/java/technologies/downloads/ 根据自己使…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...