C++实现简单的内存碎片统计 _ 空闲链表遍历算法【源码】

阿宇姑娘_6006

阿宇姑娘_6006

2026-04-09

486人浏览

原创

结论:用自定义std::list(按地址升序维护)+ 固定大小内存池即可模拟空闲链表并统计碎片;外部碎片通过遍历相邻空闲块计算地址间隙,内部碎片统计拆分后不可用的残余块(size

c++实现简单的内存碎片统计 _ 空闲链表遍历算法【源码】

怎么用 C++ 模拟空闲链表并统计内存碎片

直接说结论:不用重写 malloc,用自定义 std::list 或结构体链表 + 固定大小内存池即可完成碎片统计。核心是把“空闲块”建模为带 addr 和 size 的节点,按地址排序后遍历,计算相邻块之间的间隙(即外部碎片)和单个块内无法分配的剩余空间(即内部碎片)。

常见错误是把“碎片”等同于“小块数量多”——实际要看能否拼成目标请求尺寸。比如有 10 个 64B 空闲块,但你要分配 512B,它们之间地址不连续,就仍是碎片。

  • 初始化一个大数组模拟堆,如 char heap[1024 * 1024](1MB)
  • 维护一个 std::list<freeblock></freeblock>,其中 FreeBlock = { void* addr; size_t size; }
  • 首次将整个堆作为单个空闲块插入链表,addr = heap,size = sizeof(heap)
  • 每次分配时从链表中查找合适块(首次适配/最佳适配),拆分后更新链表
  • 释放时合并相邻空闲块(检查 addr 和 addr+size 是否紧邻)

如何识别和量化外部碎片(gap-based fragmentation)

外部碎片指空闲块之间存在的、因地址不连续而无法被利用的间隙。它不存储在空闲链表里,必须通过遍历排序后的空闲块推算。

关键点:空闲链表必须按 addr 升序排列,否则 gap 无法计算。别用 std::vector 存然后每次 sort —— 插入/删除开销大,改用 std::list + 手动插入保持有序,或 std::set<freeblock comparebyaddr></freeblock>。

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载
  • 遍历排序后的空闲块列表,对每对相邻节点 a 和 b,计算 gap = b.addr - (a.addr + a.size)
  • 若 gap > 0,说明存在外部碎片,累计到总 gap 字节数
  • 可额外统计 gap 的微小间隙数量(这类几乎无法用于任何分配)
  • 注意:最后一个块之后、第一个块之前不计入 gap(不属于堆内可用范围)

内部碎片统计不能只看 malloc 对齐

内部碎片是已分配块中未被使用的部分,常源于对齐要求或最小分配单元。但在自定义内存池中,它更常来自“拆分空闲块时的向下取整”或“用户请求尺寸与块大小不匹配”。

比如空闲块 1024B,用户请求 1000B,你按需分配后剩下 24B —— 这 24B 若小于最小分配粒度(如 16B),就成内部碎片。它仍属于空闲链表,但后续可能无法被利用。

  • 每次从空闲块 f 中分配 req_size 时,记录 f.size - req_size 为潜在内部碎片
  • 但真正计入统计的,是拆分后新加入空闲链表的那部分“残余块”,且其 size (如 8 或 16)
  • 避免重复统计:同一空闲块多次拆分,只对最终不可用的尾部残余计数
  • 不要依赖 sizeof(size_t) 或 alignof(max_align_t) 算对齐开销——你的池子对齐策略由你控制,比如统一按 16B 对齐,则每块头部加 16B 元数据,这部分也属于内部碎片

为什么 std::list 遍历比 vector 快,但合并操作容易出错

因为 std::list 是双向链表,插入/删除 O(1),维持地址有序只需找到位置后 splice;而 std::vector 每次插入都要 memmove,O(n)。但问题出在合并逻辑上:合并两个空闲块,不仅要删节点,还要确保前后指针正确,尤其当三个块 A-B-C 全部连续时,一次只合并 A+B,B+C 就会失效。

  • 释放内存时,先查前驱:是否存在块 p 满足 p.addr + p.size == freed_block.addr
  • 再查后继:是否存在块 n 满足 freed_block.addr + freed_block.size == n.addr
  • 合并顺序必须是:先和前驱合并(更新新块地址),再用新块地址判断是否能和后继合并
  • 用 std::list::erase() 删除节点后,迭代器立即失效,别存着下一轮用;改用 std::next(it) 或 it++ 前先保存下一个
  • 调试时打印链表:写个 dump_freelist(),输出每个 addr 和 size,肉眼一看就能发现断点或重叠

最易忽略的是:碎片统计必须在稳定状态下做(即所有分配/释放完成之后),中间过程的临时碎片没有意义。还有,地址比较必须用 uintptr_t 转换,别直接比 void*——某些平台下行为未定义。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

2023.09.04

1118

7

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

2025.06.09

4314

18

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

2025.07.04

4451

25

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.23

636

5

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

351

13

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

339

31

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

5187

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2288

6

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

2023.08.14

5316

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习