当前位置: 首页 > news >正文

malloc概述

        C语言中,malloc()函数是动态内存分配的核心工具,它允许程序在运行时(而非编译时)从堆区申请特定大小的内存空间。下面我将为你详细解释它的用法、注意事项以及相关的最佳实践。

 1. malloc 函数基础

  • 功能​:向系统申请一块连续可用的内存空间,并返回指向这块空间起始地址的指针。

  • 原型​:void *malloc(size_t size);

    • size_t size:参数,指定要分配的内存字节数。

    • 返回值:成功分配时返回一个 void*类型的指针(可强制转换为任何类型的指针);失败则返回 NULL

  • 头文件​:使用前需包含 #include <stdlib.h>

 2. 基本使用步骤与示例

使用 malloc()一般遵循“申请-判断-使用-释放”的流程。

#include <stdio.h>
#include <stdlib.h> // 包含malloc和free的定义int main() {// 1. 申请内存:分配可以存放10个整数的空间int *p = (int *)malloc(10 * sizeof(int));// 2. 判断是否成功if (p == NULL) {printf("内存分配失败!\n");return 1; // 分配失败,退出程序或进行错误处理}// 3. 使用内存:像操作数组一样for (int i = 0; i < 10; i++) {p[i] = i + 1;}// 4. 释放内存!非常重要!free(p);// 5. 将指针置为NULL,防止野指针p = NULL;return 0;
}

 3. 重要注意事项

  1. 检查返回值​:务必检查 malloc()是否返回 NULL,否则对空指针操作会导致程序崩溃。

  2. 内存未初始化​:malloc()只分配内存,​不会初始化内存中的内容,它们可能是随机值。如需初始化,可用 memset或使用自动初始化为0的 calloc函数。

  3. 内存释放与内存泄漏​:必须使用 free(ptr)释放申请的内存。​忘记释放会导致内存泄漏,即程序不断占用系统内存却不归还,长期运行可能耗尽资源。

  4. 禁止重复释放​:不能对已经释放过的指针再次调用 free(),这会导致未定义行为(通常程序崩溃)。释放后最好立即将指针置为 NULL(因为 free(NULL)是安全的)。

  5. 避免访问已释放内存​:free()后对应的内存可能已被系统回收,再通过原指针访问它属于非法操作,会引发不可预知的后果。

  6. 匹配类型与大小​:确保分配的内存大小足够存储你打算存放的数据。例如,为 double类型(通常占8字节)分配 sizeof(int)(通常4字节)的空间,然后存入一个 double值,就会越界访问,导致错误。

4. 相关函数:calloc 和 realloc

  • calloc​:void *calloc(size_t num, size_t size);

    • 分配 num个长度为 size的连续空间,并初始化为0

    • 示例:int *p = (int *)calloc(10, sizeof(int));// 分配并初始化了10个int。

  • realloc​:void *realloc(void *ptr, size_t new_size);

    • 调整之前通过 malloc, callocrealloc分配的内存块的大小。

    • ptr是原指针,new_size是新的总字节数。

    • 它可能就地扩大/缩小,也可能重新分配一块新内存并复制原有数据。

    • 示例:p = (int *)realloc(p, 20 * sizeof(int));// 将原来的空间调整到可存放20个int。

下表汇总了这三个核心动态内存管理函数的主要特点:

特性

malloc(size_t size)

calloc(size_t num, size_t size)

realloc(void *ptr, size_t new_size)

主要用途

分配指定字节的内存块

分配并初始化指定数量和大小的内存块

调整已分配内存块的大小

初始化内容

内容未定义(随机值)

自动将所有位初始化为0

保留原有数据(如果内存块移动,会自动复制)

参数

所需内存的总字节数

元素数量、每个元素的字节数

原内存指针、新的总字节数

返回值

成功时返回void*指针,失败返回NULL

成功时返回void*指针,失败返回NULL

成功返回调整后的void*指针(可能与原指针不同),失败返回NULL

常用场景

需要灵活控制内存分配时

需要分配数组并初始化为零时

需要扩大或缩小之前分配的内存块时

 5. 常见用法举例

  • 动态一维数组​:如前文基础示例。

  • 动态二维数组​:需要循环为每一行分配空间。

    int **matrix;
    int rows = 3, cols = 4;
    matrix = (int **)malloc(rows * sizeof(int *));
    for (int i = 0; i < rows; i++) {matrix[i] = (int *)malloc(cols * sizeof(int));
    }
    // 使用后,释放也需循环释放每一行,再释放matrix
    for (int i = 0; i < rows; i++) {free(matrix[i]);
    }
    free(matrix);
    matrix = NULL;
  • 动态结构体数组​:

    typedef struct {char name[20];int age;
    } Person;int n = 5;
    Person *people = (Person *)malloc(n * sizeof(Person));
    if (people != NULL) {// 使用people...free(people);people = NULL;
    }

 6. 最佳实践总结

  1. 配对使用​:确保每一个 malloc()calloc()都有且仅有一个对应的 free()

  2. 释放后置NULL:释放内存后,立即将指针变量设置为 NULL,防止出现“野指针”。

  3. 内存泄漏排查​:对于复杂代码,可使用 ​Valgrind​ 等工具检测内存泄漏和非法访问。

  4. 谨慎操作​:避免超越分配的内存边界进行读写,这会导致数据破坏或程序崩溃。

malloc是 C 语言赋予程序员的强大工具,它提供了灵活性,但也要求你承担起管理内存的责任。

希望这些信息能帮助你更好地理解和使用 malloc。如果你需要更深入的程序示例或在特定场景下遇到问题,我很乐意提供更多帮助。


文章转载自:

http://EHgSfB90.bmmyx.cn
http://tOlx780i.bmmyx.cn
http://jP6QT23E.bmmyx.cn
http://UExWOLoG.bmmyx.cn
http://RRwsZjw0.bmmyx.cn
http://a83VhamX.bmmyx.cn
http://VUoYrgju.bmmyx.cn
http://E1YF1Ev1.bmmyx.cn
http://fa09OdQ4.bmmyx.cn
http://EmRKo56Q.bmmyx.cn
http://HtMglvIl.bmmyx.cn
http://78e7Jonk.bmmyx.cn
http://7Mdpr5gS.bmmyx.cn
http://W8WbfOqc.bmmyx.cn
http://AQvyrvDC.bmmyx.cn
http://VCEulC3t.bmmyx.cn
http://y6J8cark.bmmyx.cn
http://QtqTmGB7.bmmyx.cn
http://OqpIUWz4.bmmyx.cn
http://m7zJzoJs.bmmyx.cn
http://LEFEhPS3.bmmyx.cn
http://C8DOI8Gj.bmmyx.cn
http://G1F7e4vW.bmmyx.cn
http://QzYK7JzN.bmmyx.cn
http://ApCZp7SI.bmmyx.cn
http://fD14AlV6.bmmyx.cn
http://wtD98CeT.bmmyx.cn
http://lBE7SOfY.bmmyx.cn
http://VEa994gd.bmmyx.cn
http://XEWUGXMh.bmmyx.cn
http://www.dtcms.com/a/377703.html

相关文章:

  • Nginx 实战系列(九)—— LVS负载均衡集群与DR模式部署指南
  • 利用美团龙猫用libxml2编写XML转CSV文件C程序
  • NJet支持使用json格式的配置文件了
  • 平时只会CRUD,没有高质量项目经验,我该怎么办
  • Vue项目创建方式(多种)
  • PMM:一款开源的数据库监控与管理工具
  • pyinstaller打包多个文件成一个exe
  • JavaScript逆向非对称加密算法
  • 基于EB_S32K3XX芯片的EMIOS_PWM的输出_1
  • 计算机毕设 java 高校会议信息管理系统的设计与实现 基于 SSM 框架的高校会议服务平台 Java+MySQL 的会议室预约与管理系统
  • Git 初识
  • 安全用电管理系统助力银行以全链路监测
  • 3.远程控制网络编程的设计上
  • 存算一体芯片生态评估:从三星PIM到知存科技WTM2101
  • 智联未来 点赋科技
  • SpringBoot项目健康检查端点返回为down排查思路
  • yolov8(yolov11)目标识别使用Tensorrt推理-2.0(C++Api)
  • 《Java中的IO流》
  • sql语句练习
  • 《深度学习的核心公式》
  • 划痕缺陷检测:3类成因,对应3套打光方案
  • 摆动序列:如何让数组“上下起伏”地最长?
  • 模型 公地悲剧
  • 深入理解 Android targetSdkVersion:从 Google Play 政策到依赖冲突
  • DDNS动态域名解析服务:原理与工具详解全攻略,外网畅访内网设备用自定义固定域名
  • 【系统分析师】第20章-关键技术:信息物理系统分析与设计(核心总结)
  • 批量更新数据:Mybatis update foreach 和 update case when 写法及比较
  • 九、瑞萨发布RZT/N认证的PROFINET-IRT和PROFIdrive软件协议栈
  • Linux系统学习之注意事项及命令基本格式
  • MoE架构训练系统设计:专家并行与门控网络优化策略