内存分配头是否需要对齐联合?

时间:2009-12-15 15:00:43

标签: c

在K& R2中,他们在第8章中实现了内存分配器。对于每个块,都有类似这样的头(来自内存,代码可能是非精确的):

union header_t
{
  struct 
  {
     unsigned size;
     unsigned* next; 
  };

  long align;
};

他们这样做是为了“确保标题在长边界上正确对齐”。但是,最大的成员并没有对齐联盟吗?结构大于单个对齐成员,因此无论如何,标题将在结构的倍数上对齐,不是吗?

什么时候结构更大(说它有很多成员)。在写内存分配器时是否总是需要这种对齐联合技巧?

3 个答案:

答案 0 :(得分:5)

K& R中的数据类型是:

union header
{
  struct 
  {
     union header *ptr; 
     unsigned size;
  } s;

  Align x;
};

让我们说我们改为:

union header_t
{
  struct 
  {
     union header_t *next; 
     unsigned size;
  } s;
};

(顺便说一句,你需要struct变量的名称,并且还要更改 struct内的指针键入union header_t *,因为 数据结构是一个链表。)

K& R的malloc()实现保留了一大块空间,然后 用它来维持免费商店。当调用此malloc时,它 在空闲列表中找到一个有足够空间的地方,并返回一个 指向它尾端的指针。

特别是,代码的相关部分是:

typedef union header Header;
static Header base;
Header *p = &base;
...
p += p->s.size;
return (void *)(p+1);

请注意,我们正在返回p+1(强制转换为void *),因此我们必须确保此指针与任何数据类型的对齐。由于p本身指向Header *,我们必须确保当我们将sizeof(Header)添加到对齐的指针时,我们会返回另一个对齐的指针(请记住,p+1sizeof(Header)指向p个字节。此要求意味着Header 与所有类型的数据对齐。

struct内的Header可能无法与最广泛的类型对齐。为了确保我们的Header类型如此对齐,我们将一个成员添加到我们知道最大对齐的union,即,是给定计算机上最宽的类型。 K& R假设此类型为long。另请注意,Header的大小是否大于Align类型的大小并不重要。 此处的假设是Align类型此处是一种具有最严格对齐要求的类型,而不是它很大。

有趣的是,我们需要假设一个'最大对齐'类型,因为C标准需要对malloc返回的指针进行任何类型的对齐,但是没有指定一种可移植的方法来找出对齐的内容。是。如果标准 指定了此类型,则可以使用该类型而不是long Align

答案 1 :(得分:1)

“结构大于单个对齐成员”。

首先,谁说?如果在您的实现中,unsignedunsigned*各为32位,long为128位(或更实际,16位和64位),该怎么办?

第二,那又怎样?即使结构至少与long一样大,也不意味着它必须至少与long一样大。如果unsignedunsigned*没有对齐要求,则结构没有对齐要求。但也许long可以。

答案 2 :(得分:0)

这些数据类型的大小取决于平台。我猜结构的两个无符号成员是16位,长对齐是结构中的32位或两个32位成员,长整数是64位。

对齐边界可以是32位或64位