什么是性能,安全性和数据成员隐藏在嵌入的字符数组在C ++类的对齐? [英] What is the Performance, Safety, and Alignment of a Data member hidden in an embedded char array in a C++ Class?

查看:231
本文介绍了什么是性能,安全性和数据成员隐藏在嵌入的字符数组在C ++类的对齐?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到一个codeBase的最近,我怕违反对齐约束。我擦洗它产生一个最小的例子,下面给出。简单地说,球员是:

I have seen a codebase recently that I fear is violating alignment constraints. I've scrubbed it to produce a minimal example, given below. Briefly, the players are:

  • 的。这是一类有效地分配内存,为有效的一些定义。 的保证返回的内存块被排列为要求的大小。

  • Pool. This is a class which allocates memory efficiently, for some definition of 'efficient'. Pool is guaranteed to return a chunk of memory that is aligned for the requested size.

* OBJ_LIST *。该类存储对象的同质集合。一旦对象的数量超​​过某一阈值,它从一个列表到树改变其内部重新presentation。的* OBJ_LIST *的大小是一个指针(8个字节在64位平台)。当然,它的人口商店将超过。

*Obj_list*. This class stores homogeneous collections of objects. Once the number of objects exceeds a certain threshold, it changes its internal representation from a list to a tree. The size of *Obj_list* is one pointer (8 bytes on a 64-bit platform). Its populated store will of course exceed that.

汇总的。此类重新presents系统中的一个非常普遍的对象。它的历史可以追溯到早期的32位工作站的时代,它被优化(在相同的32位时代),使用尽可能少的空间尽可能的结果。 汇总的S可以是空的,或管理对象的任意数字。

Aggregate. This class represents a very common object in the system. Its history goes back to the early 32-bit workstation era, and it was 'optimized' (in that same 32-bit era) to use as little space as possible as a result. Aggregates can be empty, or manage an arbitrary number of objects.

在本实施例中,的聚合的项总是从普尔取值分配的,所以它们总是对准。中* OBJ_LIST *在这个例子中,唯一出现在的汇总的对象隐藏的成员,因此他们总是使用的配售新的分配。下面是支持类:

In this example, Aggregate items are always allocated from Pools, so they are always aligned. The only occurrences of *Obj_list* in this example are the 'hidden' members in Aggregate objects, and therefore they are always allocated using placement new. Here are the support classes:

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;
};

这里是聚集。需要注意的是成员声明* member_list_store_d *:

And here is Aggregate. Note that member declaration *member_list_store_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)];
};

这是我最关心的是数据成员。这里是伪code初始化和访问:

It is that data member that I'm most concerned about. Here is the pseudocode for initialization and access:

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;
}

您可能想建议我们替换字符数组的指针在* OBJ_LIST *类型,初始化为null,或者类的一个实例。这给正确的语义,而只是转移周围的存储成本。如果内存仍然处于premium(它可能是,这是一个EDA数据库重新presentation),用指针来代替字符数组* OBJ_LIST *会时花费多了一个指针的情况下总结的对象的的拥有成员。

You may be tempted to suggest that we replace the char array with a pointer to the *Obj_list* type, initialized to NULL or an instance of the class. This gives the proper semantics, but just shifts the memory cost around. If memory were still at a premium (and it might be, this is an EDA database representation), replacing the char array with a pointer to an *Obj_list* would cost one more pointer in the case when Aggregate objects do have members.

除此之外,我真的不希望得到从这里的主要问题,这是调整分心。我的认为的上述结构是有问题的,但不能真正找到更多的标准比系统/库的调整行为有些模糊讨论的

Besides that, I don't really want to get distracted from the main question here, which is alignment. I think the above construct is problematic, but can't really find more in the standard than some vague discussion of the alignment behavior of the 'system/library' new.

那么,根据上面的结构做任何事情超过造成偶然发生的管失速?

So, does the above construct do anything more than cause an occasional pipe stall?

修改:我知道有办法的替换的使用嵌入的字符数组的方法。因此,没有原来的建筑师。他们放弃他们,因为记忆是在premium。现在,如果我有一个理由去触碰那个code,我可能会改变它。

Edit: I realize that there are ways to replace the approach using the embedded char array. So did the original architects. They discarded them because memory was at a premium. Now, if I have a reason to touch that code, I'll probably change it.

不过,我的问题,关于这个方法固有的对齐问题,就是希望大家都能解决。谢谢!

However, my question, about the alignment issues inherent in this approach, is what I hope people will address. Thanks!

推荐答案

确定 - 有机会正确读取它。你有一个定位的问题,并调用未定义行为当您访问的字符数组作为OBJ_LIST。最有可能的平台将做三件事之一:让你摆脱它,让你摆脱它在运行时的罚款或偶尔崩溃一个总线错误

Ok - had a chance to read it properly. You have an alignment problem, and invoke undefined behaviour when you access the char array as an Obj_list. Most likely your platform will do one of three things: let you get away with it, let you get away with it at a runtime penalty or occasionally crash with a bus error.

您的便携式选项来解决这一问题是:

Your portable options to fix this are:

  • 在使用malloc分配存储或 一个全球配置的功能,但 你认为这是太 昂贵的。
  • 为长Arkadiy说,让你的缓冲液OBJ_LIST成员:

  • allocate the storage with malloc or a global allocation function, but you think this is too expensive.
  • as Arkadiy says, make your buffer an Obj_list member:

Obj_list list;

但你现在不想支付建设费用。你可以通过提供一个内嵌的无操作构造减轻这仅用于创建这种情况下 - 作为发布的默认构造函数会做。如果按照这条路线,认真考虑调用析构函数

but you now don't want to pay the cost of construction. You could mitigate this by providing an inline do-nothing constructor to be used only to create this instance - as posted the default constructor would do. If you follow this route, strongly consider invoking the dtor

list.~Obj_list();

在做一个新的位置到这个存储空间。

before doing a placement new into this storage.

否则,我认为你只剩下非便携式选择:要么靠错位的访问平台的宽容,或者使用任何不可移植的选项你的编译器为您提供了

Otherwise, I think you are left with non portable options: either rely on your platform's tolerance of misaligned accesses, or else use any nonportable options your compiler gives you.

免责声明:这是完全有可能我的思念与工会或类似的把戏。这是一个不寻常的问题。

Disclaimer: It's entirely possible I'm missing a trick with unions or some such. It's an unusual problem.

这篇关于什么是性能,安全性和数据成员隐藏在嵌入的字符数组在C ++类的对齐?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆