GLIBC(2.25)中malloc分配内存时如何决定使用堆还是匿名段?
GLIBC 2.25 malloc 内存分配位置差异解析
多Arena机制导致线程间的分配差异
GLIBC malloc通过多arena设计降低线程锁竞争:
- 主线程使用主arena,其内存依托进程的堆段,通过
brk()/sbrk()系统调用扩展。 - 其他线程会创建独立的私有arena,这类arena的内存完全通过
mmap()创建匿名映射段实现。
这就是为什么切换线程后malloc分配的内存会出现在匿名段——非主线程的malloc调用会优先使用自身的私有arena,而非主arena的堆空间。
小内存分配的mmap触发场景
即便分配内存小于默认的MMAP_THRESHOLD(通常为128KB),也可能触发mmap分配:
- 当主arena的堆中没有足够连续的空闲块满足请求时,malloc会跳过堆空间查找,直接用
mmap()分配匿名块。 - 堆内存碎片严重,无法拼凑出请求大小的连续块时,也会触发mmap分配。
- 可通过
mallopt(M_MMAP_THRESHOLD, size)调整阈值,或用mallopt(M_MMAP_MAX, 0)禁用小内存的mmap分配。
内存释放后的复用逻辑影响
用mmap()分配的内存释放后会直接归还内核;堆段内存释放后会存入空闲链表,供后续分配复用。如果后续请求的大小匹配空闲链表中的块,就会复用堆内存;若没有匹配块,则可能触发堆扩展或新的mmap分配,这也会导致相同大小的请求出现不同的分配位置。
内容的提问来源于stack exchange,提问作者Kokomelom
相关产品推荐
相关产品推荐

