malloc内存分配的内存布局疑惑:内存占用与碎片问题
内存分配额外占用与内存碎片问题
问题描述
调试发现:指针d与f地址差80字节,f与new_p地址差32字节,两个int*指针地址差也为32字节。即malloc分配struct data实际占用80字节,分配int占用32字节,存在明显内存浪费。最初发现f与d间有16字节间隙,考虑过结构体内存对齐,但struct data的name数组占64字节,理应能正确对齐。请问该现象的原因是什么?是否会导致严重内存碎片?
相关代码
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <sys/types.h> struct data { char name[64]; }; struct fp { int (*fp)(); }; void winner() { printf("level passed\n"); } void nowinner(){ printf("level has not been passed\n"); } int main(int argc, char **argv) { struct data *d; struct fp *f; d = malloc(sizeof(struct data)); f = malloc(sizeof(struct fp)); int* new_p = malloc(sizeof(int)); int* new_p2 = malloc(sizeof(int)); f->fp = nowinner; printf("data is at %p, fp is at %p\n", d, f); strcpy(d->name, argv[1]); f->fp(); }
使用的GCC版本
gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc.
问题解答
现象原因
这是glibc内存分配器(ptmalloc2)的内存块元数据管理和预分配机制导致的,和结构体内存对齐无关:
- ptmalloc2会为每个
malloc分配的内存块添加头部元数据,包含块大小、空闲标记、前后块指针等信息,在64位系统下,这个基础头部通常占用16字节。 - 同时,ptmalloc2对小内存块采用固定尺寸的预分配桶策略:为了提升分配效率、减少碎片,会把小内存块归类到若干固定尺寸的分配池里。
- 你的
struct data本身占64字节,加上16字节的元数据,总占用刚好80字节,这就是d和f地址差80的原因。 - 单个
int仅占4字节,加上元数据后远小于32字节,但ptmalloc2会直接分配最小规格的预分配桶(32字节),所以两个int*的地址差为32字节。
- 你的
是否会导致严重内存碎片?
通常不会:
- ptmalloc2内置了空闲块合并机制,当相邻的内存块都被释放后,会自动合并成大的空闲块,避免零散碎片累积。
- 这种预分配桶的设计,本质是为了复用相同尺寸的内存块,减少因频繁小尺寸分配产生的碎片——相同规格的内存块释放后可以直接分配给后续同尺寸的请求。
- 只有在频繁分配/释放不同尺寸的小内存块,且无法合并的极端场景下,才会产生明显碎片,但你的场景中都是固定尺寸的分配,出现严重碎片的风险极低。
内容的提问来源于stack exchange,提问作者user19987806
相关产品推荐
相关产品推荐

