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

zah*_*pov 3 c

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

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

  long align;
};
Run Code Online (Sandbox Code Playgroud)

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

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

Alo*_*hal 5

K&R中的数据类型是:

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

  Align x;
};
Run Code Online (Sandbox Code Playgroud)

假设我们改为:

union header_t
{
  struct 
  {
     union header_t *next; 
     unsigned size;
  } s;
};
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,您需要struct变量的名称,并且还要更改structto类型中的指针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);
Run Code Online (Sandbox Code Playgroud)

请注意,我们返回p+1(强制转换void *),因此我们必须确保此指针与任何数据类型对齐.由于p它本身指向a Header *,我们必须确保当我们添加sizeof(Header)到对齐的指针时,我们得到另一个对齐的指针(记住,p+1指向来自的sizeof(Header)字节p).这一要求意味着,Header 拥有对所有类型的数据保持一致.

struct内部Header可能不适合最广泛的类型可能的排列.为了确保我们的Header类型如此对齐,我们将一个成员添加到union我们知道最大对齐的成员,即,是给定计算机上最宽的类型.K&R假设这种类型是long.另外,请注意,如果大小Header大于Align类型的大小,则无关紧要. 这里的假设是Align这里的类型是一种具有最严格的对齐要求的类型,而不是它很大.

有趣的是,我们需要假设一个"最大对齐"类型,因为C标准要求从返回的指针对任何类型进行对齐malloc,但是没有指定一种可移植的方法来找出该对齐将是什么.如果标准确实指定了这样的类型,那么可以使用该类型而不是longfor Align.