在K& R2中,他们在第8章中实现了内存分配器。对于每个块,都有类似这样的头(来自内存,代码可能是非精确的):
union header_t
{
struct
{
unsigned size;
unsigned* next;
};
long align;
};
他们这样做是为了“确保标题在长边界上正确对齐”。但是,最大的成员并没有对齐联盟吗?结构大于单个对齐成员,因此无论如何,标题将在结构的倍数上对齐,不是吗?
什么时候结构更大(说它有很多成员)。在写内存分配器时是否总是需要这种对齐联合技巧?
答案 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+1
从sizeof(Header)
指向p
个字节。此要求意味着Header
已与所有类型的数据对齐。
struct
内的Header
可能无法与最广泛的类型对齐。为了确保我们的Header
类型如此对齐,我们将一个成员添加到我们知道最大对齐的union
,即,是给定计算机上最宽的类型。 K& R假设此类型为long
。另请注意,Header
的大小是否大于Align
类型的大小并不重要。 此处的假设是Align
类型此处是一种具有最严格对齐要求的类型,而不是它很大。
有趣的是,我们需要假设一个'最大对齐'类型,因为C标准需要对malloc
返回的指针进行任何类型的对齐,但是没有指定一种可移植的方法来找出对齐的内容。是。如果标准 指定了此类型,则可以使用该类型而不是long
Align
。
答案 1 :(得分:1)
“结构大于单个对齐成员”。
首先,谁说?如果在您的实现中,unsigned
和unsigned*
各为32位,long
为128位(或更实际,16位和64位),该怎么办?
第二,那又怎样?即使结构至少与long
一样大,也不意味着它必须至少与long
一样大。如果unsigned
和unsigned*
没有对齐要求,则结构没有对齐要求。但也许long
可以。
答案 2 :(得分:0)
这些数据类型的大小取决于平台。我猜结构的两个无符号成员是16位,长对齐是结构中的32位或两个32位成员,长整数是64位。
对齐边界可以是32位或64位