【C语言】内存管理

【C语言】内存管理

文章目录

  • 【C语言】内存管理
    • 1.概念
    • 2.库函数
    • 3.动态分配内存
      • malloc
      • calloc
    • 4.重新调整内存的大小和释放内存
      • realloc
      • free

1.概念

C 语言为内存的分配和管理提供了几个函数。这些函数可以在 <stdlib.h> 头文件中找到。

在 C 语言中,内存是通过指针变量来管理的。指针是一个变量,它存储了一个内存地址,这个内存地址可以指向任何数据类型的变量,包括整数、浮点数、字符和数组等。C 语言提供了一些函数和运算符,使得程序员可以对内存进行操作,包括分配、释放、移动和复制等。

2.库函数

序号函数及描述
1void *calloc(int num, int size);
在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为0。所以它的结果是分配了 num * size 个字节长度的内存空间,并且每个字节的值都是0。
2void free(void *address);
该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。
3void *malloc(int num);
在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。
4void *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 是动态内存分配的核心函数之一,在需要处理不确定数量的数据或实现某些数据结构(如链表、树等)时非常有用。正确使用 mallocfree 对于编写稳健和高效的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 语言中的一个用于内存管理的函数,它允许你更改先前使用 malloccalloc 函数分配的内存块的大小。这个函数非常有用,当你需要调整一个数据结构的大小以适应程序运行时变化的需求时。

函数原型

void *realloc(void *ptr, size_t new_size);
  • ptr 是指向先前分配的内存块的指针。
  • new_size 是新的内存大小,单位是字节。

功能描述

  • realloc 尝试将指针 ptr 指向的内存块调整为 new_size 字节大小。
  • 如果 ptrNULLrealloc 表现得就像 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 语言中用于释放之前使用 malloccallocrealloc 函数分配的动态内存的标准库函数。正确地使用 free 函数对于防止内存泄漏和有效管理程序的内存使用至关重要。

函数原型

void free(void *ptr);
  • ptr 是指向要释放的内存块的指针。如果 ptrNULL,调用 free 没有效果,但这种调用是安全的,不会引发错误。

功能描述

  • free 函数的作用是将之前动态分配的内存块返回给操作系统或运行时环境,使其可以被其他部分的程序再次使用。
  • 当没有更多的内存可用于新的内存分配请求时,释放不再需要的内存块是一种良好的编程实践。

注意事项

  • 释放NULL指针:根据 C 标准,尝试释放一个 NULL 指针是安全的,free 将不做任何操作。
  • 悬挂指针:释放内存后,指针指向的内存已经不再属于你的程序,因此不应再使用该指针(称为悬挂指针)。
  • 内存泄漏:如果忘记了调用 free 来释放动态分配的内存,将导致内存泄漏,长期运行的程序可能会因此耗尽可用内存。
  • 重复释放:不应尝试多次释放同一块内存,这可能会导致未定义的行为或程序崩溃。

使用 free 函数是 C 语言编程中的一个重要方面,它确保了程序的健壮性和资源的有效使用。记住,每次使用 malloccallocrealloc 分配内存时,都应该在适当的时候使用 free 来释放内存。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/10664.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【游戏设计原理】96 - 成就感

成就感是玩家体验的核心&#xff0c;它来自完成一件让自己满意的任务&#xff0c;而这种任务通常需要一定的努力和挑战。游戏设计师的目标是通过合理设计任务&#xff0c;不断为玩家提供成就感&#xff0c;保持他们的参与热情。 ARCS行为模式&#xff08;注意力、关联性、自信…

MySQL CTE:解锁SQL查询新模式

目录 一、CTE 初相识 二、CTE 基础语法 &#xff08;一&#xff09;基本语法结构 &#xff08;二&#xff09;语法规则详解 三、非递归 CTE 应用实例 &#xff08;一&#xff09;单 CTE 简单查询 &#xff08;二&#xff09;多 CTE 联合查询 四、递归 CTE 深入探索 &…

C#,入门教程(12)——数组及数组使用的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(11)——枚举&#xff08;Enum&#xff09;的基础知识和高级应用https://blog.csdn.net/beijinghorn/article/details/123917587https://blog.csdn.net/beijinghorn/article/details/123917587 数组是一种数据集合&#xff0c;是一组…

【leetcode练习·二叉树】计算完全二叉树的节点数

本文参考labuladong算法笔记[拓展&#xff1a;如何计算完全二叉树的节点数 | labuladong 的算法笔记] 如果让你数一下一棵普通二叉树有多少个节点&#xff0c;这很简单&#xff0c;只要在二叉树的遍历框架上加一点代码就行了。 但是&#xff0c;力扣第第 222 题「完全二叉树的…

低代码系统-产品架构案例介绍、轻流(九)

轻流低代码产品定位为零代码产品&#xff0c;试图通过搭建来降低企业成本&#xff0c;提升业务上线效率。 依旧是从下至上&#xff0c;从左至右的顺序 名词概述运维层底层系统运维层&#xff0c;例如上线、部署等基础服务体系内置的系统能力&#xff0c;发消息、组织和权限是必…

对顾客行为的数据分析:融入2+1链动模式、AI智能名片与S2B2C商城小程序的新视角

摘要&#xff1a;随着互联网技术的飞速发展&#xff0c;企业与顾客之间的交互方式变得日益多样化&#xff0c;移动设备、社交媒体、门店、电子商务网站等交互点应运而生。这些交互点不仅为顾客提供了便捷的服务体验&#xff0c;同时也为企业积累了大量的顾客行为数据。本文旨在…

MSA Transformer

过去的蛋白质语言模型以单个序列为输入&#xff0c;MSA Transformer以多序列比对的形式将一组序列作为输入。该模型将行和列注意力交织在输入序列中&#xff0c;并在许多蛋白质家族中使用mask语言建模目标进行训练。模型的性能远超过了当时最先进的无监督学习方法&#xff0c;其…

QT实现有限元软件操作界面

本系列文章致力于实现“手搓有限元&#xff0c;干翻Ansys的目标”&#xff0c;基本框架为前端显示使用QT实现交互&#xff0c;后端计算采用Visual Studio C。 本篇将二维矩形截面梁单元&#xff08;Rect_Beam2D2Node&#xff09;组成的钢结构桥作为案例来展示软件功能。 也可以…

推荐一款好用的翻译类浏览器扩展插件

给大家推荐一款实用的翻译工具——沉浸式翻译。这是一款免费、高效的AI驱动浏览器扩展插件&#xff0c;能够帮助用户轻松打破语言障碍&#xff0c;享受沉浸式的阅读体验。 主要特性 沉浸式阅读体验&#xff1a;通过智能识别网页主内容区域并进行双语对照翻译&#xff0c;让用户…

ElasticSearch-文档元数据乐观并发控制

文章目录 什么是文档&#xff1f;文档元数据文档的部分更新Update 乐观并发控制 最近日常工作开发过程中使用到了 ES&#xff0c;最近在检索资料的时候翻阅到了 ES 的官方文档&#xff0c;里面对 ES 的基础与案例进行了通俗易懂的解释&#xff0c;读下来也有不少收获&#xff0…

开源的瓷砖式图像板系统Pinry

简介 什么是 Pinry &#xff1f; Pinry 是一个开源的瓷砖式图像板系统&#xff0c;旨在帮助用户轻松保存、标记和分享图像、视频和网页。它提供了一种便于快速浏览的格式&#xff0c;适合喜欢整理和分享多种媒体内容的人。 主要特点 图像抓取和在线预览&#xff1a;支持从网页…

Java 大视界 -- Java 大数据在自动驾驶中的数据处理与决策支持(68)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【数据结构】初识链表

顺序表的优缺点 缺点&#xff1a; 中间/头部的插入删除&#xff0c;时间复杂度效率较低&#xff0c;为O(N) 空间不够的时候需要扩容。 如果是异地扩容&#xff0c;增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间&#xff0c;会有不小的消耗。 扩容可能会存在…

I.MX6ULL 中断介绍上

i.MX6ULL是NXP&#xff08;原Freescale&#xff09;推出的一款基于ARM Cortex-A7内核的微处理器&#xff0c;广泛应用于嵌入式系统。在i.MX6ULL中&#xff0c;中断&#xff08;Interrupt&#xff09;是一种重要的机制&#xff0c;用于处理外部或内部事件&#xff0c;允许微处理…

4-图像梯度计算

文章目录 4.图像梯度计算(1)Sobel算子(2)梯度计算方法(3)Scharr与Laplacian算子4.图像梯度计算 (1)Sobel算子 图像梯度-Sobel算子 Sobel算子是一种经典的图像边缘检测算子,广泛应用于图像处理和计算机视觉领域。以下是关于Sobel算子的详细介绍: 基本原理 Sobel算子…

苍穹外卖——数据统计

在商家管理端的左侧&#xff0c;有一个名为"数据统计"的菜单&#xff0c;该页面负责展示各个维度的数据统计&#xff0c;分别是营业额统计、用户统计、订单统计、销量排名top10。统计的数据是借助一些图形化的报表技术来生成并展示的。在左上角还可选择时间段&#x…

优盘恢复原始容量工具

买到一个优盘&#xff0c;显示32mb&#xff0c;我见过扩容盘&#xff0c;但是这次见到的是缩容盘&#xff0c;把2g的容量缩成32MB了&#xff0c;首次见到。。用芯片查询工具显示如下 ChipsBank(芯邦) CBM2199E 使用以下工具&#xff0c;恢复原始容量。。 其他CMB工具可能不行…

Flutter Candies 一桶天下

| | | | | | | | 入魔的冬瓜 最近刚入桶的兄弟&#xff0c;有责任心的开发者&#xff0c;对自己的项目会不断进行优化&#xff0c;达到最完美的状态 自定义日历组件 主要功能 支持公历&#xff0c;农历&#xff0c;节气&#xff0c;传统节日&#xff0c;常用节假日 …

[Collection与数据结构] B树与B+树

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

ROS应用之SwarmSim在ROS 中的协同路径规划

SwarmSim 在 ROS 中的协同路径规划 前言 在多机器人系统&#xff08;Multi-Robot Systems, MRS&#xff09;中&#xff0c;SwarmSim 是一个常用的模拟工具&#xff0c;可以对多机器人进行仿真以实现复杂任务的协同。除了任务分配逻辑以外&#xff0c;SwarmSim 在协同路径规划方…