You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:52:47