具有虚拟函数GCC / Xcode的类的大小 [英] Size of classes with virtual functions GCC/Xcode
问题描述
任何人都可以向我解释这里发生了什么?首先,我认为大多数程序员知道一个带有虚函数的类有一个vtbl,因此在它的顶部有4个额外的字节。据我所知,这是相当标准。我测试了这个,并利用这个事实,然后从一个二进制文件加载到适当的vtbls。在过去的6个月中,我一直在Xcode工作,最近遇到了需要做一些负载在原地的东西,所以我正在研究修补vtbls。为了确保我的理解是正确的,我写了一个示例程序。这是:
class A
{
public:
virtual int getData
{
return a;
}
virtual void print()
{
printf(hello\\\
);
}
int a;
};
class B:public A
{
public:
int getData()
{
return b;
}
int b;
};
class C:public B
{
public:
int getData()
{
return c;
}
void print()
{
printf(world\\\
);
}
int c;
};
class D
{
public:
int a;
int b;
};
int main(int argc,const char * argv [])
{
A * tA = new A();
tA-> a = 1;
printf(A:%d \\\
,sizeof(A));
printf(A data:%d\\\
,tA-> getData());
B * tB = new B();
tB-> a = 2;
tB-> b = 4;
printf(B:%d \\\
,sizeof(B));
printf(B data:%d\\\
,tB-> getData());
C * tC = new C();
tC-> c = 8;
printf(C:%d \\\
,sizeof(C));
printf(C data:%d\\\
,tC-> getData());
A * aC = tC;
aC-> print();
printf(D:%d \\\
,sizeof(D));
return 0;
}
我的预期输出为:
答:8
:A $ b
B:12 B:12
b $ b C:16 C数据:8 世界 但是,我得到的输出是: A:16 A数据:1 B:16 b $ b B数据:4 C:24 C数据:8 世界 b $ b D:8 任何人都知道这里发生了什么?谢谢! 类A到C的实例包含一个vptr,一个指向动态类型的虚函数表的指针。此指针在64位机器上占用8个字节(或32位机器上的4个字节)。每个int成员占用4个字节。 sizeof(Class)的最小值是所有成员的sizeof(成员)的总和。如果是这样,那么 但是,这只是最小大小。编译器通常将此大小增加到sizeof(void *)的倍数,这是8个字节。这个过程称为对齐。它可能看起来像这样浪费内存,但是这超过了性能增益:CPU可以比非对齐数据更快地读取对齐的数据。 顺便说一句,你的预期结果将是正确的,如果你在一个32位机器。指针(esp。vptr)在那里有4个字节宽,并且对齐也是4个字节的倍数。因为所有类的所有数据成员都是4字节大,那么对齐方式将不会做任何事情。 Can anyone explain to me what is going on here? First off, I think most programmers know that a class with a virtual function has a vtbl and thus has 4 extra bytes on the top of it. As far as I know, that's fairly standard. I've tested this and taken advantage of this fact before to do load in place from a binary file with patched vtbls. For the last 6 months, I've been working in Xcode and just recently came across the need to do some load in place stuff, so I was looking into patching vtbls again. Just to make sure my understanding was correct, I wrote a sample program. Here it is: My expected output was: A: 8 A data: 1 B: 12 B data: 4 C: 16 C data: 8 world D: 8 However, the output I'm getting is: A: 16 A data: 1 B: 16 B data: 4 C: 24 C data: 8 world D: 8 Anybody have any idea what's going on here? Thanks! Instances of classes A through C contain a vptr, a pointer to the virtual function table for the dynamic type. This pointer occupies 8 bytes on your 64-bit machine (or 4 bytes on a 32-bit machine). Each int member takes up 4 bytes. The minimum value of sizeof(Class) is the sum of sizeof(member) for all members. If it were like that, then However, this is only the minimum size. Compilers usually increase this size to a multiple of sizeof(void*), which is 8 bytes here. This process is called aligning. It may look like this wastes memory, but this is outweighed by a performance gain: The CPU can read aligned data much faster than non-aligned data. By the way, your expected result would have been correct if you were on a 32-bit machine. Pointers (esp. vptr) are 4 bytes wide there, and alignment is also to multiples of 4 bytes. Since all data members of the classes in question are 4 bytes big then, alignment wouldn't do anything there. 这篇关于具有虚拟函数GCC / Xcode的类的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
sizeof(A)= 8(vptr)+ 4(int a)= 12
sizeof(B)= 8(vptr)+ 4(int a)+ 4(int b)= 16
sizeof(C)= 8(vptr) + 4(int c)= 20
sizeof(D)= 4(int a)+ 4(int b)= 8
class A
{
public:
virtual int getData()
{
return a;
}
virtual void print()
{
printf("hello\n");
}
int a;
};
class B : public A
{
public:
int getData()
{
return b;
}
int b;
};
class C : public B
{
public:
int getData()
{
return c;
}
void print()
{
printf("world\n");
}
int c;
};
class D
{
public:
int a;
int b;
};
int main (int argc, const char * argv[])
{
A* tA = new A();
tA->a = 1;
printf("A: %d\n", sizeof(A));
printf("A data: %d\n", tA->getData());
B* tB = new B();
tB->a = 2;
tB->b = 4;
printf("B: %d\n", sizeof(B));
printf("B data: %d\n", tB->getData());
C* tC = new C();
tC->c = 8;
printf("C: %d\n", sizeof(C));
printf("C data: %d\n", tC->getData());
A* aC = tC;
aC->print();
printf("D: %d\n", sizeof(D));
return 0;
}
sizeof(A) = 8 (vptr) + 4 (int a) = 12
sizeof(B) = 8 (vptr) + 4 (int a) + 4 (int b) = 16
sizeof(C) = 8 (vptr) + 4 (int a) + 4 (int b) + 4 (int c) = 20
sizeof(D) = 4 (int a) + 4 (int b) = 8