【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/ 根据自己使…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
