我最近看到一个代码库,我担心它违反了对齐约束。我已经对其进行了擦洗,以生成一个最小的示例,如下所示。简而言之,球员们是:
Pool。对于“高效”的某些定义,这是一个有效分配内存的类。Pool保证返回一块与请求大小对齐的内存块。
Obj_list。此类存储同构对象集合。一旦对象的数量超过某个阈值,它就会将其内部表示从列表更改为树。的大小Obj_list是一个指针(在 64 位平台上为 8 个字节)。其店面的客流量当然会超过这个数字。
总计的。该类代表系统中非常常见的对象。它的历史可以追溯到早期的 32 位工作站时代,并且它经过“优化”(在同一个 32 位时代)以使用尽可能少的空间。总计的s 可以为空,也可以管理任意数量的对象。
在这个例子中,总计的项目总是从分配Pools,所以它们总是对齐的。唯一出现的情况是Obj_list在此示例中是“隐藏”成员总计的对象,因此它们总是使用分配安置新。以下是支持类:
class Pool
{
public:
Pool();
virtual ~Pool();
void *allocate(size_t size);
static Pool *default_pool(); // returns a global pool
};
class Obj_list
{
public:
inline void *operator new(size_t s, void * p) { return p; }
Obj_list(const Args *args);
// when constructed, Obj_list will allocate representation_p, which
// can take up much more space.
~Obj_list();
private:
Obj_list_store *representation_p;
};
这是聚合。注意会员声明会员列表商店_d:
// Aggregate is derived from Lesser, which is twelve bytes in size
class Aggregate : public Lesser
{
public:
inline void *operator new(size_t s) {
return Pool::default_pool->allocate(s);
}
inline void *operator new(size_t s, Pool *h) {
return h->allocate(s);
}
public:
Aggregate(const Args *args = NULL);
virtual ~Aggregate() {};
inline const Obj_list *member_list_store_p() const;
protected:
char member_list_store_d[sizeof(Obj_list)];
};
这是我最关心的数据成员。这是初始化和访问的伪代码:
Aggregate::Aggregate(const Args *args)
{
if (args) {
new (static_cast<void *>(member_list_store_d)) Obj_list(args);
}
else {
zero_out(member_list_store_d);
}
}
inline const Obj_list *Aggregate::member_list_store_p() const
{
return initialized(member_list_store_d) ? (Obj_list *) &member_list_store_d : 0;
}
您可能会建议我们将 char 数组替换为指向Obj_list类型,初始化为 NULL 或类的实例。这给出了正确的语义,但只是改变了内存成本。如果内存仍然非常宝贵(可能是这样,这是 EDA 数据库表示形式),请将 char 数组替换为指向Obj_list在这种情况下会多花费一个指针总计的物体do有会员。
除此之外,我真的不想分散对这里主要问题的注意力,即对齐。我think上述构造是有问题的,但除了对“系统/库”的对齐行为的一些模糊讨论之外,在标准中找不到更多内容new.
那么,上述结构除了导致偶尔的管道停顿之外还有其他作用吗?
Edit: 我意识到有办法replace使用嵌入式 char 数组的方法。最初的建筑师也是如此。他们丢弃了它们,因为内存非常宝贵。现在,如果我有理由接触该代码,我可能会更改它。
然而,我希望人们能够解决我的问题,即这种方法固有的一致性问题。谢谢!