malloc 内存分配机制:brk 与 mmap

article/2025/6/6 3:49:09

 一、malloc的两种内存分配策略

malloc 并非直接的系统调用,而是C标准库封装的内存管理函数。它根据应用程序请求的内存大小,智能地选择两种不同的底层机制向操作系统申请内存:

  1. 小块内存分配 (< 128KB):brk() / sbrk() 系统调用

    • 原理: 操作程序的堆顶指针(program break)。通过 brk() 或 sbrk() 将堆顶向高地址方向移动,扩展堆空间,从而获得一块新的连续内存区域。

    • 释放行为: 调用 free() 释放这块内存时,内存通常不会立即归还给操作系统!释放的内存块会被 malloc 的实现(如 ptmallocglibc 的分配器)放入其维护的内部空闲内存池(bins) 中。后续的 malloc 请求会优先从这些池子中寻找合适大小的空闲块复用,避免了频繁的系统调用。

    • 优点: 对于频繁分配释放的小块内存,复用缓存池效率极高。

    • 缺点: 容易在堆内产生内存碎片。大量小内存的分配释放可能导致堆中存在许多小的、不连续的空闲块,虽然总量够用,但无法满足稍大的连续内存请求(外部碎片)。长期运行的程序可能看到堆的“最高水位”不断升高。

  2. 大块内存分配 (>= 128KB):mmap() 系统调用

    • 原理: 在进程的内存映射区域(位于堆和栈之间,通常用于加载共享库、文件映射等)开辟空间。采用 MAP_ANONYMOUS | MAP_PRIVATE 标志,表示分配一块与文件无关、私有的匿名内存。

    • 释放行为: 调用 free() 释放这块内存时,内存会通过 munmap() 系统调用立即归还给操作系统。这块虚拟地址空间和对应的物理内存会被真正释放。

    • 优点: 大块内存单独管理,释放彻底,避免了大块内存长时间占用堆空间导致的外部碎片问题

    • 缺点: 每次分配和释放都涉及系统调用,开销相对较大;每次分配的虚拟地址在初次访问时都会触发缺页中断(Page Fault)以建立物理映射。

二、为什么不是单一策略?

理解 malloc 混合使用 brk 和 mmap 的动机,是掌握其设计精髓的关键:

  1. 为什么不全部使用 mmap

    • 系统调用开销巨大: 每次 mmap 分配都需要从用户态切换到内核态,执行分配逻辑,再切换回用户态。munmap 释放亦然。对于程序中大量、高频的小内存分配(例如几字节到几KB的对象、字符串、结构体),这种开销极其昂贵,会严重拖慢程序性能。

    • 缺页中断开销: mmap 新分配的页面处于“未映射”状态。当程序第一次读写该内存时,会触发缺页中断,由内核分配物理页框并建立映射。虽然 brk 扩展的新区域首次访问也需缺页中断,但 mmap 每次分配的新区域都独立,几乎必然触发新的中断,而 brk 扩展的区域可能是连续的。

  2. 为什么不全部使用 brk

    • 内存碎片: 想象一下,如果所有内存(包括几百MB的大数组)都从堆里分配。程序频繁地分配、释放不同大小的内存块,尤其是大量小块内存,会导致堆内散布着无数小的、不连续的空闲缝隙。即使总的空闲内存足够,也可能无法找到一块连续的、足够大的空间来满足一次较大的 malloc 请求。这就是外部碎片问题。长期运行的程序可能会因为碎片耗尽可用连续空间而崩溃,即使 free 了很多内存。

    • “膨胀”的堆永不收缩: 使用 brk 分配的堆空间,即使 free 了其中的大部分内存,堆顶通常也不会降低(分配器缓存了这些空闲块)。这导致进程的常驻内存集(RSS) 看起来居高不下,可能影响系统整体内存调度和资源监控。

三、使用malloc的注意事项与陷阱

  • 内存泄漏(Memory Leak): 这是最常见也最严重的问题。分配了内存 (malloc), 但忘记释放 (free),或者释放前丢失了指向该内存的唯一指针。程序不断泄漏,最终耗尽可用内存。务必确保分配与释放成对出现,尤其在分支、循环和错误处理路径中。

  • 内存碎片(Memory Fragmentation): 如前所述,brk 策略容易导致外部碎片,mmap 策略对大内存释放更彻底。对于需要长时间运行、频繁分配释放的程序,碎片管理尤为重要。可以考虑使用对象池、内存池等技术缓解。

  • 野指针(Dangling Pointer):

    int *p = (int *)malloc(10 * sizeof(int));
    free(p);  // p 指向的内存已被释放(可能被系统回收或放入缓存池)
    // p 此时是野指针!
    *p = 42;  // 未定义行为!可能导致崩溃、数据损坏等严重后果。

    关键: free(p) 仅释放 p 指向的内存块,并不会改变指针变量 p 本身的值(它仍然指向那块已释放内存的地址)。 安全做法是释放后立即将指针置为 NULL

    free(p);
    p = NULL; // 拴住野指针,后续操作NULL指针通常能更快暴露错误(如崩溃)

  • 检查分配成功: malloc 在内存不足时会返回 NULL永远不要假设 malloc 一定成功!

    int *ptr = (int *)malloc(large_size);
    if (ptr == NULL) {
        // 处理内存分配失败:记录错误、优雅降级或退出
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }

总结与对比:brk vs mmap

特性brk / sbrk (用于 < 128KB)mmap (用于 >= 128KB)
分配区域堆 (Heap)内存映射区域 (Memory Mapped Region)
释放行为缓存到内存池,不立即归还OSmunmap立即归还OS
主要优点高效 (缓存复用,减少系统调用/缺页)避免大块外部碎片,释放彻底
主要缺点易产生内存碎片,堆可能“膨胀”开销大 (系统调用、缺页中断)
适用场景高频、小块内存分配低频、大块内存分配

malloc采用brk和mmap两种方式结合的策略,是在内存分配效率、内存管理和系统资源利用之间取得的一种平衡。了解这些底层实现逻辑,有助于我们在编写 C 程序时更加合理地使用动态内存分配,避免常见的内存问题,提高程序的性能和稳定性。


http://www.hkcw.cn/article/DLVPCVhkdY.shtml

相关文章

【AI News | 20250603】每日AI进展

AI Repos 1、dgm 是一个创新的自改进系统&#xff0c;通过迭代修改自身代码并利用编码基准验证每次更改&#xff0c;实现开放式进化。该系统旨在提升 AI 代理的代码修改能力。DGM 支持 OpenAI 和 Anthropic API&#xff0c;依赖 Docker 环境&#xff0c;并集成了 SWE-bench 和…

Rust 学习笔记:Cargo 工作区

Rust 学习笔记&#xff1a;Cargo 工作区 Rust 学习笔记&#xff1a;Cargo 工作区创建工作区在工作区中创建第二个包依赖于工作区中的外部包向工作区添加测试将工作区中的 crate 发布到 crates.io添加 add_two crate 到工作区总结 Rust 学习笔记&#xff1a;Cargo 工作区 随着项…

操作系统 第 39 章 插叙:文件和目录

两项关键操作系统技术的发展&#xff1a;进程&#xff0c;虚拟化的 CPU&#xff1b;地址空间&#xff0c;虚拟化的内存。 这一部分加上虚拟化拼图中最关键的一块&#xff1a;持久存储。永久存储设备永久地&#xff08;或至少长时间地&#xff09;存储信息&#xff0c;如传统硬盘…

楼宇自控系统联动暖通空调:解密建筑环境舒适度提升路径

走进现代建筑&#xff0c;无论是办公场所、商业中心&#xff0c;还是医院、酒店&#xff0c;人们对环境舒适度的要求越来越高。暖通空调作为调节建筑室内环境的关键设备&#xff0c;其运行效果直接影响着人们的体验。然而&#xff0c;传统暖通空调独立运行、调控不灵活等问题&a…

Freemarker快速入门

Freemarker概述 FreeMarker 是一款 模板引擎&#xff1a; 即一种基于模板和要改变的数据&#xff0c; 并用来生成输出文本(HTML网页&#xff0c;电子邮件&#xff0c;配置文件&#xff0c;源代码等)的通用工具。 它不是面向最终用户的&#xff0c;而是一个Java类库&#xff0c…

黑盒(功能)测试基本方法

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、黑盒测试的概念 1、什么是黑盒测试 &#xff08;1&#xff09;黑盒测试又称功能测试、数据驱动测试或基于规格说明书的测试&#xff0c;是一种从用户观点出…

[java八股文][JavaSpring面试篇]SpringCloud

了解SpringCloud吗&#xff0c;说一下他和SpringBoot的区别 Spring Boot是用于构建单个Spring应用的框架&#xff0c;而Spring Cloud则是用于构建分布式系统中的微服务架构的工具&#xff0c;Spring Cloud提供了服务注册与发现、负载均衡、断路器、网关等功能。 两者可以结合…

chromedriver 下载失败

问题描述 chromedriver 2.46.0 下载失败 淘宝https://registry.npmmirror.com/chromedriver/2.46/chromedriver_win32.zip无法下载 解决方法 找到可下载源 https://cdn.npmmirror.com/binaries/chromedriver/2.46/chromedriver_win32.zip &#xff0c;先将其下载到本地目录(D…

74. 搜索二维矩阵 (力扣)

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。…

CppCon 2014 学习:Rolling Your Own Circuit Simulator

这段话讲述了一个背景和动机&#xff0c;目的是阐明为什么开源C库变得越来越复杂且在科学和工程领域有很大的应用潜力。 关键点&#xff1a; 开源库的成熟&#xff1a; 近年来&#xff0c;开源C库在许多科学和工程领域变得越来越成熟和强大。这些库不再仅仅是简单的工具&…

无人机自主降落论文解析

Dynamic Landing of an Autonomous Quadrotor on a Moving Platform in Turbulent Wind Conditions 滑膜控制器 这一部分详细介绍了边界层滑模控制器&#xff08;Boundary Layer Sliding Controller&#xff0c;BLSC&#xff09;的设计和实现&#xff0c;特别是如何将其应用于…

.NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想

在当今数据驱动的时代&#xff0c;向量数据库&#xff08;Vector Database&#xff09;作为一种新兴的数据库技术&#xff0c;正逐渐成为软件开发领域的重要组成部分。特别是在 .NET 生态系统中&#xff0c;向量数据库的应用为开发者提供了构建智能、高效应用程序的新途径。 一…

html基础01:前端基础知识学习

html基础01&#xff1a;前端基础知识学习 1.个人建立打造 -- 之前知识的小总结1.1个人简历展示1.2简历信息填写页面 1.个人建立打造 – 之前知识的小总结 1.1个人简历展示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&qu…

CentOS Stream 8 Unit network.service not found

一、问题现象 在 CentOS Stream 8 操作系统中&#xff0c;配置完静态IP 信息&#xff0c;想重启网络服务。 执行如下命令&#xff1a; systemctl restart network 提示信息如下&#xff1a; Failed to restart network.service: Unit network.service not found. 二、问题…

【Axure高保真原型】交通事故大屏可视化分析案例

今天和大家分享交通事故大屏可视化分析案例的原型模板&#xff0c;包括饼图分类分析、动态显示发生数、柱状图趋势分析、中部地图展示最新事故发现地点和其他信息、右侧列表记录发生事故的信息…… 通过多种可视化图表展示分析结果&#xff0c;具体效果可以点击下方视频观看或…

网络安全-等级保护(等保) 3-3-1 GB/T 36627-2018 附录A (资料性附录) 测评后活动、附 录 B (资料性附录)渗透测试的有关概念说明

################################################################################ GB/T 36627-2018 《信息安全技术 网络安全等级保护测试评估技术指南》对网络安全等级保护测评中的相关测评技术进行明确的分类和定义,系统地归纳并阐述测评的技术方法,概述技术性安全测试和…

wsl===windows下安装Linux系统

新近版本的windows都支持了Linux&#xff0c;操作如下&#xff1a; 控制面板中启用对应的功能 2. 打开powershell&#xff0c;以安装Ubuntu为例&#xff0c;然后执行 PS C:\Users\steven.wang> wsl.exe --update 正在安装: 适用于 Linux 的 Windows 子系统 已安装 适用于 …

云上展厅颠覆传统展览

云上展厅&#xff1a;重塑展览行业的新篇章 随着数字化技术的迅猛发展&#xff0c;传统展览模式正经历一场深刻的变革。云上展厅&#xff0c;新兴的展览形式&#xff0c;正逐步颠覆传统的实体展览模式&#xff0c;凭借其跨越时空限制、多样化展示方式、丰富互动体验及高效商业…

谷歌地图苹果版v6.138.2 - 前端工具导航

谷歌地图(Google maps)苹果版是是由谷歌官方推出的一款手机地图应用。软件功能强大&#xff0c;支持本地搜索查找世界各地的地址、地点和商家&#xff1b;支持在街景视图中查看世界各地的360度全景图&#xff1b;支持查找乘坐火车、公交车和地铁的路线&#xff0c;或者查找步行…

Microsoft前后端不分离编程新风向:cshtml

文章目录 什么是CSHTML&#xff1f;基础语法内联表达式代码块控制结构 布局页面_ViewStart.cshtml_Layout.cshtml使用布局 模型绑定强类型视图模型集合 HTML辅助方法基本表单验证 局部视图创建局部视图使用局部视图 高级特性视图组件依赖注入Tag Helpers 性能优化缓存捆绑和压缩…