C中的malloc内存分配方案

我在C中试验了malloc,我观察到malloc在分配了一些内存后浪费了一些空间。 下面是我用来测试malloc的代码片段

#include  #include  int main(){ char* a; char* b; a=malloc(2*sizeof(char)); b=malloc(2*sizeof(char)); memset(a,9,2); memset(b,9,2); return 0; } 

在下图的右中间(为清晰起见,在新选项卡中打开图像),您可以看到内存内容; 0x804b008是变量’a’指向的地址,0x804b018是变量’b’指向的内存。 从0x804b00a 0x804b017到内存发生了什么? 即使我尝试分配3*sizeof(char)而不是2*sizeof(char)字节的内存,内存布局是相同的! 那么,有什么我想念的吗?

gdb接口

允许malloc()浪费尽可能多的空间 – 标准没有指定任何有关实现的内容。 唯一的保证是关于对齐( §7.20.3内存管理function ):

如果分配成功,则返回指针,以便可以将其指定给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到空间被明确释放) 。

您的实现似乎返回最小8字节对齐的指针。

记忆对齐! 这对于x86中的性能是有利的,并且在ARM等某些体系结构中是强制性的。

大多数CPU要求对象和变量驻留在系统内存中的特定偏移处。 例如,32位处理器需要一个4字节的整数驻留在一个可被4整除的存储器地址。这个要求称为“存储器对齐”。 因此,一个4字节的int可以位于存储器地址0x2000或0x2004,但不能位于0x2001。 在大多数Unix系统上,尝试使用未对齐的数据会导致总线错误,从而完全终止程序。 在英特尔处理器上,支持使用未对齐的数据,但性能会受到严重影响。 因此,大多数编译器会根据数据类型和所使用的特定处理器自动对齐数据变量。 这就是结构和类占用的大小通常大于其成员总和的原因

http://www.devx.com/tips/Tip/13265

堆由实现处理,不一定如您所期望的那样。 标准明确不保证有关订单或连续性的任何信息。 有两个主要因素导致使用的堆空间比您要求的多。

首先,必须对齐已分配的内存,以便它适合任何类型的对象使用。 通常,计算机期望N个字节的原始数据对象以N的倍数分配,因此可能无法使malloc()返回不是8的倍数的值。

其次,需要管理堆,以便free()允许重用内存。 这意味着堆管理器需要跟踪已分配和未分配的块及其大小。 一种做法是在每个块之前将一些信息粘贴到内存中,这样管理器就可以知道要释放的块大小以及可以重用的块。 如果这是你的系统所做的,那么在分配的块之间将使用更多的内存,并且在8字节给定对齐限制时,你可能无法获得少于16字节的分配。

大多数现代malloc()实现以2的幂分配并具有最小分配大小,以减少碎片,因为奇数球大小通常只有在足够的连续分配free()时才能重复使用free() d来制作更大的块。 (它还加速了整合的连续分配,IIRC。)还要记住块开销; 要获得块大小,您需要添加一些金额(GNU malloc() ,IIRC中的8个)以供内部管理使用。

malloc只保证返回一块至少和你给它一样大的内存块。 但是,当处理器在内存块上运行时,处理器通常更有效,这些内存块以内存中的8个字节的倍数开始。 查找字大小以获取更多信息。