我如何理解fdump-class-hierarchy输出 [英] How can I understand the fdump-class-hierarchy output

查看:307
本文介绍了我如何理解fdump-class-hierarchy输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用fdump-class-hierarchy编译器选项,但是我不知道如何理解输出。 大小,对齐,基本大小和基本对齐是什么意思,它们是如何计数的?谢谢!



代码为:

  A类
{
公开:

私有:
double m_thing;
int m_number;
};

输出为:

  A类
大小= 16对齐= 8
基本大小= 16基本对齐= 8
A(0x406c690)0

但是,如果我稍微改变一下课程:

  class A 
{
public:

private:
int m_number;
double m_nothing;
};

输出将是:

  A类
大小= 16对齐= 8
基本大小= 12基本对齐= 8
A(0x406c690)0


解决方案

大小 align 是用作完整类型的类的大小和对齐方式。也就是说,如果创建的对象的完整类型就是该类型(例如定义该类型的变量,或者将该类型与 new 一起使用)。



大小只是它占用的字节数。因此 size = 16 意味着当用作完整类型时,它总是占用16个字节。



对齐方式告诉您在哪里可以放置对象: align = 8 表示对象的地址必须是8的整数倍。



基大小基对齐给出了大小和对齐方式,以防将该类用作基类。它们之所以不同,是因为C ++标准允许对象在用作基类时使用较少的填充。



因此,让我们具体看一下您的示例(我假设在第一种情况下,您实际上在 double 之前有 int )。我还省略了 public private ,因为在这里它们不会更改任何内容(如果您同时拥有public或私有数据成员,它们原则上可以进行某些更改,但我不知道是否有任何编译器会利用它)。我还在猜测 int double 的大小和对齐方式(实际上,我认为这些值是很常见的选择,并解释得到的值)。



因此,在第一种情况下(我假设),您有

  A类
{
int m_number;
double m_nothing;
};

现在 int 的大小和对齐方式 4 ,而double的大小和对齐方式为 8



让我们完成编译器的工作并构建我们的类。



首先,我们有 m_number ,它占用4个字节。我们必须按照给定的顺序排列成员,所以 m_number 放在 A 的开头:

  iiii 

到现在为止,我们的大小为4(int的四个字节),并且对齐方式为4(因为int的对齐方式为4)。但是现在我们必须添加一个double(大小和对齐方式8)。由于紧接int之后,我们在(相对)地址4处,所以我们没有正确地为double对齐,因此我们必须添加4个 padding 字节(我将在其中标记 * )达到8的倍数。因此,我们上课了:

 现在,如果将该类用作基类,那么我们就结束了。因此,我们假设 base size = 16  base align = 8 (我们需要将8对齐以获得



对于完整的对象,还有另一个考虑因素:标准要求在数组中,对象彼此跟随,且彼此之间没有间隙。也就是说,对象之后的第一个字节必须与下一个对象正确对齐。最终,这意味着完整对象的尺寸必须是其对齐方式的倍数。



现在,我们发现的对象布局已满足该要求。因此,我们也可以将其不变地用于完整对象。因此,对于整个对象,我们得到 size = 16 align = 8



现在考虑顺序被颠倒的情况:

  A类
{
double m_nothing;
int m_number;
};

现在我们必须从 double 开始:

  dddddddd 

下一步,我们必须添加 int 。事实证明,下一个空闲位置已经正确地对齐了 int ,因此我们可以附加它:

  ddddddddiiii 

现在用作基础对象,我们准备好了。如您所见,我们只需要12个字节,因此 base size = 12 。当然,要正确对齐 double ,对象必须再次从8的倍数的地址开始。因此,我们有 base align = 8



但是,作为起诉的完整对象,我们现在发现下一个地址将位于位置12,即 not double 成员正确对齐。因此,我们必须添加填充字节,直到再次到达正确对齐的地址为止:

  ddddddddiiii **** 

如您所见,现在我们需要16个字节,因此 size = 16 。由于加倍,我们仍然有 align = 8



请注意,对齐要求会极大地影响一类。例如,考虑以下两种类型:

  struct S1 
{
char c1;
double d1;
char c2;
double d2;
char c3;
};

结构S2
{
double d1;
double d2;
char c1;
char c2;
char c3;
};

虽然它们都包含相同的成员,但 S1 具有上述大小和对齐方式的对象的总(非基本)大小为40,而 S2 的总大小仅为24。实际上,类型 S1 作为完整对象,看起来像

  c **** *** ddddddddc ******* ddddddddc ******* 

类型为 S2

  ddddddddddddddddccc ***** 

因此,最重要的是,具有最高对齐要求的成员应始终排在首位。



还要注意, sizeof 返回完整对象的大小,即类层次结构转储调用的大小 size


I'm playing with fdump-class-hierarchy compiler option but I don't know how I can understand the output. What does the "size", "align", "base size" and "base align" mean, and how these are counted? Thanks!

When the code is:

class A
{
public:

private:
    double m_nothing;
    int m_number;
};

The output is:

Class A
   size=16 align=8
   base size=16 base align=8
A (0x406c690) 0

But, if I change the class a little:

class A
{
public:

private:
    int m_number;
    double m_nothing;
};

the output will be:

Class A
   size=16 align=8
   base size=12 base align=8
A (0x406c690) 0

解决方案

The size and align are the size and alignment of the class when used as complete type. That is, if you create objects whose complete type is that type (like defining variables of that type, or using that type with new).

The size is simply the number of bytes it occupies. So size=16 means when used as complete type, it always occupies 16 bytes.

The alignment tells you where the object may be placed: align=8 means the address of the object must be an integer multiple of 8.

The base size and base align give the size and alignment in case the class is used as base class. The reason why they are different is that the C++ standard allows objects to use less padding when used as base class.

So let's look specifically at your example (I'm assuming that you actually have the int before the double in the first case). I'm also omitting the public and private because here they don't change anything (if you had both public or private data members, they could in principle change something, but I don't know if any compiler takes advantage of that). I'm also guessing the size and alignment of int and double (actually the values I assume are pretty common choice, and explain the values you get).

So in the first case (I assume) you have

class A
{
  int m_number;
  double m_nothing;
};

Now int has size and alignment 4, and double has size and alignment 8.

So let's do the job of the compiler and build our class.

First, we have m_number, which occupies 4 bytes. We have to put the members in the order given, so m_number goes at the beginning of A:

iiii

Up to now, we have size 4 (the four bytes for the int), and alignment 4 (because int has alignment 4). But now we have to add a double (size and alignment 8). Since directly after the int, we are at (relative) address 4, we are not correctly aligned for the double, so we have to add 4 padding bytes (which I'll mark with *) to get to a multiple of 8. Thus we get for our class:

iiii****dddddddd

Now, if the class is used as base class, we are finished. Thus we habe base size=16 and base align=8 (we need an alignment of 8 in order to get the double aligned correctly).

For the complete object, there's another consideration: The standard demands that in arrays, the objects follow each other without a gap in between. That is, the first byte after the object must be correctly aligned for the next object. Which ultimately means that the size of the complete object has to be a multiple of its alignment.

Now the object layout we've found already fulfils that requirement. Therefore we can use it unchanged also for the complete object. Therefore we get size=16 and align=8 for the complete object.

Now consider the case where the order is reversed:

class A
{
  double m_nothing;
  int m_number;
};

Now we have to start with the double:

dddddddd

Next, we have to add the int. As it turns out, the next free place is already correctly aligned for an int, therefore we can just append it:

ddddddddiiii

Now for the use as base object, we are ready. As you can see, we only needed 12 bytes, therefore base size=12. Of course for the double to be correctly aligned, the object again has to start at an address which is a multiple of 8. Therefore we have base align=8.

However for the sue as complete object, we now find that the next address would be at position 12, which is not correctly aligned for the double member. Therefore we have to add padding bytes until we reach a correctly aligned address again:

ddddddddiiii****

As you can see, now we need 16 bytes, thus size=16. We still have align=8 due to the double.

Note that the alignment requirement can dramatically affect the size of a class. Consider for example the following two types:

struct S1
{
  char c1;
  double d1;
  char c2;
  double d2;
  char c3;
};

struct S2
{
  double d1;
  double d2;
  char c1;
  char c2;
  char c3;
};

While both contain the same members, S1 will with the sizes and alignments above have a total (non-base) size of 40, while the total size of S2 will be just 24. Indeed, the objects of type S1 will, as complete object, look like

c*******ddddddddc*******ddddddddc*******

while those of type S2 will look like

ddddddddddddddddccc*****

So the bottom line is that members with the highest alignment requirement should always come first.

Also note that sizeof returns the size of complete objects, that is, what the class hierarchy dump calls size.

这篇关于我如何理解fdump-class-hierarchy输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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