【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/ 根据自己使…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...

react菜单,动态绑定点击事件,菜单分离出去单独的js文件,Ant框架
1、菜单文件treeTop.js // 顶部菜单 import { AppstoreOutlined, SettingOutlined } from ant-design/icons; // 定义菜单项数据 const treeTop [{label: Docker管理,key: 1,icon: <AppstoreOutlined />,url:"/docker/index"},{label: 权限管理,key: 2,icon:…...

CMS内容管理系统的设计与实现:多站点模式的实现
在一套内容管理系统中,其实有很多站点,比如企业门户网站,产品手册,知识帮助手册等,因此会需要多个站点,甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...

篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...