Chromium 代码库不是只使用malloc()。
例如:
其中PartitionAlloc的实现位于src\base\allocator\partition_allocator目录中,是一个独立的库:

PartitionAlloc.md对这个模块进行了系统的描述。简而言之,PartitionAlloc 是一个针对空间效率、分配延迟和安全性进行优化的内存分配器。
PartitionAlloc.md 文档对里面的技术细节有详细的描述。本文进行概要总结,快速帮助读者掌握PartitionAlloc的设计思想和价值。
PartitionAlloc 的核心特性包括:
具体而言,通过减少逻辑的分支(使得CPU执行时流水线高度并发)、快速路径中的操作数量极少(使得快速路径性能极高)、使用线程缓存避免锁的使用(提高线程并发度),三个途径提高性能。

kAlignment(64位系统16B,32位系统8B)。
PartitionPageMetadata结构来追踪每一个分区页面,这个结构可能是一个SlotSpanMetadata(图中的"v")或者一个SubsequentPageMetadata(图中的"+")。SuperPagePayloadBegin()函数。总结而言,PartitionAlloc 通过多层次的策略确保了高性能和高安全性,特别注重于内存分配的效率和防止内存越界和地址重用等安全威胁。
内存分配器目标在编译时定义了平台特有的选择,涉及用于服务malloc/new调用的分配器和额外钩子。相关的构建时标志包括use_allocator_shim和use_partition_alloc_as_malloc。
默认情况下,除了iOS(尚未支持)和NaCl(无计划支持)之外的所有平台都启用这些标志。
此外,当使用sanitizer(例如asan、msan等)构建时,分配器和shim层都会被禁用。
分配器目标提供了Windows shim层所需的链接器标志。base目标(几乎)是唯一依赖于分配器的目标。除了少数在链接单元范围内不直接或间接依赖于base的可执行文件/动态库之外,没有其他目标应依赖于它。
更重要的是,除/base之外的任何地方都不应依赖于特定的分配器。
如果需要此类功能依赖,应当通过base中的抽象来实现(参见/base/memory/)。
base依赖于分配器?因为base需要提供依赖于实际分配器实现的服务。过去,base试图表现为分配器无关,依赖由其他层注入。这最终导致了一团乱麻。
有关更多背景信息,请参阅分配器清理文档。
那些在某种程度上依赖于base的链接器单元目标(代码库中的大多数目标)自动获得了正确的链接器标志集,以便在需要时拉入Windows shim层。
此目录仅包含分配器(即shim)层,该层在不同的底层内存分配实现之间切换。
在大多数平台上,Chrome覆盖了malloc/operator new符号(以及相应的free/delete和其他变体)。这是为了强制执行安全检查,并最近启用了memory-infra堆分析器。
历史上,每个平台在其代码库的不同地方有其特殊的逻辑来定义分配器符号。统一的分配器shim是一个旨在将符号定义和分配器路由逻辑统一到一个中心位置的项目。
完整文档:分配器shim设计文档。
当前状态:在Android、CrOS、Linux、Mac OS和Windows上可用并默认启用。
跟踪问题:crbug.com/550886。
构建时标志:use_allocator_shim。
分配器shim由三个阶段组成:
malloc符号定义
这个阶段负责覆盖malloc、free、operator new、operator delete等符号,并将这些调用路由到分配器shim内部。
这由allocator_shim_override_*中的头文件处理。
在Windows上:Windows的UCRT(通用C运行时)导出了弱符号,我们可以在allocator_shim_override_ucrt_symbols_win.h中覆盖它们。
在Linux/CrOS上:分配器符号作为导出的全局符号在allocator_shim_override_libc_symbols.h(对于malloc、free等)和allocator_shim_override_cpp_symbols.h(对于operator new、operator delete等)中定义。
这使malloc符号在主可执行文件和任何第三方库中得到适当的拦截。在Linux上的符号解析是一个从根链接单元开始的广度优先搜索,即可执行文件(参见便携格式规范:EXECUTABLE AND LINKABLE FORMAT (ELF))。
在Android上:与Linux/CrOS的情况不同,加载时的符号拦截是不可能的。这是因为Android进程是从预加载了libc.so的Androidzygote通过fork()创建的,稍后通过dlopen()加载本机代码(从dlopen()加载的库中的符号有不同的解析范围)。
在这种情况下,不是通过链接时(即在构建期间)包装符号解析,而是使用--Wl,-wrap,malloc链接器标志。
使用此包装标志会导致:
Chrome代码库中对分配器符号的所有引用都被重写为对__wrap_malloc及其同类的引用。__wrap_malloc符号在allocator_shim_override_linker_wrapped_symbols.h中定义,并将分配器调用路由到shim层内部。
对原始malloc符号(通常由系统的libc.so定义)的引用可通过特殊符号__real_malloc及其同类访问(将在加载时针对malloc进行重定位)。
简而言之,这种方法对动态加载器是透明的,它仍然看到对malloc符号的未定义引用。
这些符号将像往常一样针对libc.so进行解析。
Shim层实现
这个阶段包含了实际的shim实现。这包括:
一个单链表的调度器(带有指向类似malloc函数的函数指针的结构体)。调度器可以在运行时动态插入(使用InsertAllocatorDispatchAPI)。它们可以拦截并覆盖分配器调用。
安全检查(通过std::new_handler在malloc失败时自杀等)。
这发生在allocator_shim.cc中。
最终分配器路由
上述调度器链的最终元素在构建时静态定义,并最终将分配器调用路由到实际的分配器(如上文背景部分所述)。这由allocator_shim_default_dispatch_to_*文件中的头文件处理。