<!-- title: 538万人看他手写malloc -->
<!-- domain: programming -->

# 538万人围观他手写malloc：一条底层神课的深度解读

## 概述

在所有人都在讨论AI写代码的2026年，一条“逆流而上”的视频却持续狂飙：Low Level频道的《I wrote my own memory allocator in C to prove a point》（我用C手写一个内存分配器，只为证明一件事），据本刊2026年5月20日采集的频道页数据，播放量已达约538万。它不蹭热点、没有花哨动画，就是一个人、一块白板、一段C代码，把每个程序员每天都在调用、却几乎没人真正看过的`malloc`拆开重写了一遍。这条视频值得深读的原因在于：它回答的是一个不会过时的问题——**当你按下`malloc`这个按钮，机器那头到底发生了什么**。读完本文，你没看过视频也能掌握它的全部骨架；看过视频的读者，则能拿到一份它没来得及展开的“理论地图”。

## 视频基本信息

| 项目 | 内容 |
|------|------|
| 视频标题 | I wrote my own memory allocator in C to prove a point（我用C手写内存分配器，只为证明一件事） |
| 频道 | Low Level（@LowLevelLearning） |
| 主理人 | Ed（据本刊此前频道盘点，安全工程师、软件安全研究员出身） |
| 频道订阅量 | 数十万至百万量级（本刊2026年年中多次快照在50万+至110万之间，口径不一） |
| 播放量 | 约538万（据本刊2026年5月20日频道页采集数据，此后应继续增长；单一快照、未经第二来源交叉） |
| 发布时间/时长 | 本刊未采集到精确值，此处省略 |
| 观看方式 | 频道页 [youtube.com/@LowLevelLearning](https://www.youtube.com/@LowLevelLearning)，站内检索标题即可 |

## 核心主张拆解：五幕剧

这条视频的叙事结构非常经典——**从“你以为的”走到“它实际的”**，共五幕，层层递进。

### 第一幕：malloc根本不是系统调用

视频的第一个颠覆性事实是：`malloc`并不直接找操作系统要内存。它是一个**库函数**，住在glibc（Linux上的C标准库）里，真正的系统调用另有其人。调用`malloc`时，绝大多数情况下发生的事情是：**库在自己维护的“仓库”里翻找一块合适的空闲内存，把它交给你**——全程不进内核。只有仓库空了，才会动用真正的重武器向内核要货。这个“用户态库”与“内核”的分层，是理解一切后续复杂性的起点：操作系统只管“给你一大块”，至于这一大块怎么切成千上万个小块、谁用哪块、怎么回收，全是C库自己的事。

### 第二幕：向内核要内存的两种姿势：brk与mmap

视频从这里开始动手写代码。实现一个分配器的第一步，是从内核拿到原始内存。Linux提供了两条经典路径，视频把两条都走了一遍：

- **brk/sbrk**：把“堆顶指针”往后推。相当于对内核说“我的堆再长一段”。拿到的是一段连续地址空间，切起来方便，但只能长在堆这个特定区域；
- **mmap**：直接向内核申请一段全新的映射。灵活、可指定位置、归还时可以整块退回，但建立映射的代价更高。

这两条路径的分工一直保留到今天的glibc里：**小块内存走堆（brk扩展），大块内存（glibc默认阈值在128KB量级，新版本还会动态调整，据glibc文档）直接走mmap**。你在代码里`malloc`了200MB，那块内存的来路和`malloc`了200字节完全不同——这正是很多“反直觉性能现象”的源头。

### 第三幕：空闲链表与两种朴素策略：首次适配与最佳适配

拿到原始内存后，核心问题变成：**成千上万次“要内存/还内存”之后，怎么记住哪些块是空闲的？** 视频给出的答案是教科书级的：把空闲块串成一条**空闲链表（free list）**，每个空闲块的开头记下“我有多大、下一个空闲块在哪”。

然后在链表上找块，视频实现了两种最经典的策略：

- **首次适配（First Fit）**：从头扫，遇到第一块够大的就用。快，但链表头部会迅速碎化；
- **最佳适配（Best Fit）**：扫完整条链表，找能装下的最小块。看似省内存，实则每次都留下最细碎的边角料。

视频最有价值的一幕在这里：它让你**亲眼看着碎片化在几次分配-释放循环里长出来**——明明总空闲空间还够，却再也找不到一块连续内存放得下你的请求。这种“自由了，但用不了”的外部碎片，是所有动态内存系统的宿命，从malloc到文件系统到数据库存储引擎，无一幸免。

### 第四幕：为什么glibc的ptmalloc要复杂十倍

写完玩具分配器后，视频把镜头拉回现实：**为什么你机器上的malloc要复杂得多？** 答案有三层：

1. **并发**。2026年的CPU动辄几十核，如果所有线程抢一把全局锁来分配内存，锁本身就会成为瓶颈。glibc的ptmalloc引入了**多arena**与**线程本地缓存（tcache，glibc 2.26引入）**：每个线程先从自己的小仓库无锁拿内存，仓库空了才去共享区域补货——这个“分层缓存”思想和CPU缓存、数据库缓冲池一模一样；
2. **碎片与局部性**。真实分配器的策略远不止首次/最佳适配，还要考虑块大小分级、合并方向、甚至“刚释放的内存大概率很快被再次用到”这类访问模式；
3. **安全**。视频作者是安全工程师出身，这也是它区别于普通教学视频的地方：堆是黑客的主战场。释放后使用（UAF）、重复释放（double free）、堆布局操纵，全都发生在“分配器元数据”这一层。现代glibc为此加入了各种加固机制（如2020年glibc 2.32引入的safe-linking指针混淆，据glibc发行说明）。

### 第五幕："prove a point"到底证明了什么

标题里的"prove a point"是整条视频的题眼。作者证明的不是“我能写出比glibc更好的malloc”——恰恰相反，写完之后你会对glibc肃然起敬。他证明的是：**malloc没有魔法**。剥开术语，它的内核就是“空闲链表+查找策略+切分合并”三个朴素构件的组合；而它的一切“复杂”，都是在为并发、碎片、安全这三个现实问题买单。理解了这一点，你就获得了对整个系统软件世界的解码器：数据库的缓冲池、内核的SLAB、JVM的堆、GC的分代——全是同一套思想的变奏。

## 知识与理论溯源：这一课在计算机科学谱系里的坐标

这条视频看似“手工作坊”，实则每一步都踩在真实的研究传统上。

**动态存储分配的经典理论**。首次适配与最佳适配的系统研究可以追溯到Donald Knuth《计算机程序设计艺术》第一卷第2.5节"Dynamic Storage Allocation"，Knuth早在20世纪60年代就分析了这些策略，并给出了著名的“漫游指针”（roving pointer）优化——让每次查找从上次停下的地方继续，避免链表头部反复被扫描。1995年，Paul R. Wilson等四人发表了计量级的综述《Dynamic Storage Allocation: A Survey and Critical Review》，用大量模拟实验给出了一个反直觉结论：**最佳适配在真实负载下往往并不最优，碎片化程度取决于策略与工作负载的耦合，而非策略本身的好坏**。这条视频让普通观众用肉眼复现了这篇论文的动机。

**工业级分配器的谱系**。视频提到的ptmalloc，源自Doug Lea的dlmalloc——Lea在个人论文《A Memory Allocator》里完整记录了设计动机，这段文字至今是分配器设计的必读文献；Wolfram Gloger将其改造为支持多线程的ptmalloc并进入glibc。此后Google的Sanjay Ghemawat写出tcmalloc（线程缓存 malloc 的集大成者），Jason Evans为FreeBSD写出jemalloc（后成为FreeBSD默认分配器，并在超大规模场景中广泛使用），微软研究院的Daan Leijen在2019年发布了以简洁著称的mimalloc。这一脉的共同主题正是视频第五幕的结论：**为多核并发而设计**。

**内核侧的呼应**。用户态malloc的“分层缓存”思想，在内核里有精确的对应物：Sun工程师Jeff Bonwick 1994年的论文《The Slab Allocator: An Object-Caching Kernel Memory Allocator》为SunOS 5.4设计了对象缓存的SLAB分配器；Linux后来演化出SLAB/SLUB/SLOB三种实现，2007年Linux 2.6.23起SLUB成为默认。本刊资料库中收录的技术演讲《Linux Kernel Memory Allocation: SLAB, SLUB, and SLOB》正是这段历史的影像版。

**2026年的现实语境**。这条视频的走红还踩在一个大时代的鼓点上：内存安全已成为软件工程的核心议题。据微软MSRC与谷歌Chrome团队先后公布的数据，两家各自约七成的严重安全漏洞源于内存安全问题；2024年2月，美国白宫国家网络主任办公室发布报告，明确呼吁产业界向内存安全语言迁移；Rust自Linux 6.1起正式进入内核。当“用Rust消灭C的内存错误”成为主叙事时，恰好有一群人想问：**被替代的一方到底是怎么工作的？** 这条538万播放的视频，就是这个问题最流行的答案。

## 批判性审查：哪些该信，哪些要打折

**证据充分的部分**。视频的每一行代码都可以在你的机器上复现：brk/mmap是POSIX标准接口，空闲链表与两种适配策略是教科书内容，碎片化的演示是确定性现象。这部分是“看得见摸得着”的知识，可信度最高。视频的核心结论——真实malloc的复杂性来自并发、碎片与安全三方压力——与上述Knuth、Wilson、Lea、Bonwick一脉的文献完全吻合，属于学界与工业界共识。

**需要打折的部分**。其一，玩具分配器没有覆盖真实系统的关键维度：内存对齐、多线程锁、异常安全、元数据校验都被刻意省略，观众不应误以为“分配器不过如此”——视频的实际走向恰恰相反。其二，播放量数据方面，本刊只掌握2026年5月20日的单一快照（约538万），无第二来源交叉，读者引用时请注明口径；频道订阅数在不同快照间差异较大（50万+至110万），同样只作量级参考。其三，“懂了分配器就能写出更快的代码”这一隐含承诺要谨慎接受：绝大多数业务代码的性能瓶颈在算法与I/O，而非malloc本身；分配器知识是“诊断时的手电筒”，不是“日常的锤子”——否则容易滑向过早优化。

**一个容易被忽略的细节**。播放量与正确性无关，但这条视频的评论区恰恰是二次学习资源：大量讨论围绕“tcache投毒”“为什么free之后的指针还能读”展开，作者本人的回复常有安全工程师视角的补充。看视频不看评论区，会漏掉这条视频约三成的价值。

## 认知提升与实用启示

**1. 给自己的程序做一次“分配器透视”。** 你不需要手写malloc，但可以用现成工具看见它：用 AddressSanitizer（`-fsanitize=address`）或valgrind跑一遍自己的程序，观察分配热点与内存泄漏；用glibc的`mallopt`/环境变量（如`MALLOC_ARENA_MAX`）体验一下多线程程序里arena数量的影响。一次实验胜过十篇博客——这正式视频"prove a point"精神的日常化版本。

**2. 在正确的场景里“少分配”。** 理解了“每次malloc都是一次链表查找+潜在的加锁”之后，性能优化就有了一个可靠的直觉方向：热路径上的小对象，考虑对象池、arena或批量分配——这也是C++社区John Lakos等人力推arena分配器的原因（见延伸阅读）。原则只有一条：先测量，后优化，让profiler而不是情怀做决定。

**3. 学会“从最小实现开始读源码”的方法论。** 这条视频示范了一种可迁移的读码策略：读不懂glibc的ptmalloc，就先读玩具版；读不懂玩具版，就先自己写一遍。从“能跑的最小版本”到“工业级实现”之间的每一层复杂度，都对应一个真实问题——把每个问题命名出来，复杂度就不再是恐惧而是清单。这个方法对读数据库引擎、读内核、读任何大型系统都成立。

## 视频论证结构图

```mermaid
flowchart TB
    A["用户代码调用 malloc(size)"] --> B{"这块内存走哪条路？"}
    B -->|"小块：常规路径"| C["空闲链表 free list<br/>首次适配 / 最佳适配"]
    B -->|"大块：超过阈值"| D["直接 mmap 向内核申请<br/>释放时整块归还"]
    C --> E["链表里找不到合适的块？<br/>用 brk 扩展堆顶"]
    C --> F["找到块：一分为二<br/>前半交给用户，后半留在链表"]
    F --> G["用户调用 free(ptr)"]
    E --> G
    D --> G
    G --> H{"相邻块也是空闲？"}
    H -->|"是"| I["合并 coalesce：对抗碎片"]
    H -->|"否"| J["重新挂回空闲链表"]
    I --> K["外部碎片：<br/>总空间够，连续空间不够"]
    J --> K
    K --> L["现实压力一：多核并发<br/>tcache 线程缓存 / 多 arena"]
    K --> M["现实压力二：安全攻防<br/>UAF、double free、堆布局攻击"]
    L --> N["结论：malloc 没有魔法<br/>= 空闲链表 + 查找策略 + 切分合并<br/>复杂度都是为现实买单"]
    M --> N
```

## 延伸阅读

1. [Local ("Arena") Memory Allocators — John Lakos (CppNow)](https://www.youtube.com/watch?v=CVbnjydW5M0) — C++社区对arena分配器（区域内存池）的系统论述，是本文"少分配"建议的理论纵深。
2. [Linux Kernel Memory Allocation: SLAB, SLUB, and SLOB](https://www.youtube.com/watch?v=_xdNWSobYMM) — 内核侧的内存分配三实现，与用户态malloc对照观看，能看懂"分层缓存"思想如何贯穿整个系统。

## 参考来源

1. [Low Level 频道页（@LowLevelLearning）](https://www.youtube.com/@LowLevelLearning) — 本文主视频《I wrote my own memory allocator in C to prove a point》所在频道，站内检索标题即可观看；播放量数据据本刊2026年5月20日采集快照（约538万）。
2. [Low Level Academy](https://lowlevel.academy/) — 频道主理人的配套课程站点（据本刊2026年6月频道盘点采录）。
3. [Local ("Arena") Memory Allocators — John Lakos (CppNow)](https://www.youtube.com/watch?v=CVbnjydW5M0) — arena分配器主题演讲（本刊2026年7月9日采录）。
4. [Linux Kernel Memory Allocation: SLAB, SLUB, and SLOB](https://www.youtube.com/watch?v=_xdNWSobYMM) — Linux内核内存分配器技术演讲（本刊2026年7月9日采录）。

> 历史理论锚点说明：Knuth《计算机程序设计艺术》卷一§2.5、Wilson等1995年《Dynamic Storage Allocation: A Survey and Critical Review》、Doug Lea《A Memory Allocator》、Jeff Bonwick 1994年SLAB论文等文献信息为领域公开常识，本文未附链接；涉及glibc版本特性（tcache、safe-linking、mmap阈值）均据glibc官方发行说明与手册页的公开记载，未做逐条实时核验。

---
> 本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵**爱卫生**（微信ID: gprshome201101）维护，聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。
> 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
