2011-06-17 99 views
4

我正在用C中的malloc进行实验,我发现malloc在分配内存后会浪费一些空间。下面是我用来测试的mallocC中的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

+0

除了下面的答案,值得指出sizeof(char)= 1的定义,所以没有一点乘以它。 –

+0

@richardkettlewell这是正确的..但我已习惯于任何方式使用它的可读性 – nagavamsikrishna

回答

8

malloc()被允许,因为它要浪费尽可能多的空间 - 该标准没有指定任何实施。你具有的唯一保证是大约对准(§7.20.3内存管理功能):

的指针返回,如果分配成功被适当地对准,使得它可以被分配给一个指针到任何类型的对象然后用于在分配的空间中访问这样的对象或这样的对象的数组(直到空间被明确地解除分配)。

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

+0

什么是您指的是7.20.3?这是C标准书的一个章节吗?如果是这样,你能否指给我那本书。 – nagavamsikrishna

+1

@ vamsi,是的,它来自C规范。 PDF链接:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf –

3

Memory Alignment!这对x86的性能很有好处,在ARM等一些体系结构中也是强制性的。

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

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

0

大多数现代malloc()实施的总和分配中的两个大国,有一个最小的分配大小,以减少碎片因为古怪的大小通常只能在足够的连续分配free()d才能制作更大的块时重新使用。 (它也加速了整体连续分配,IIRC。)还要记住块开销;要获得块大小,您需要添加一些金额(8 GNU malloc(),IIRC)内部管理使用。

0

malloc只能保证返回一块内存,至少与您给它的大小一样大。但是,处理器在以内存8个字节的倍数开始的内存块操作时通常效率更高。查询字大小了解更多信息。

2

堆由实现处理,不一定像您期望的那样。该标准明确不保证任何有关顺序或连续性。有两个主要的原因会导致使用更多的堆空间,而不是您所要求的。

首先,分配的内存必须对齐,以便适用于任何类型的对象。通常情况下,计算机希望N字节的原始数据对象以N的倍数分配,因此您不能得到malloc()以返回不是8的倍数的值。

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