C中的malloc内存分配方案

时间:2011-06-17 16:55:01

标签: c malloc

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

#include <stdlib.h>
#include <string.h>

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 interface

5 个答案:

答案 0 :(得分:8)

允许

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

  

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

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

答案 1 :(得分:3)

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

  

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

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

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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