Class Size with GCC / Xcode Virtual Functions

Can someone explain to me what is going on here? Firstly, I think most programmers know that a class with a virtual function has vtbl and, therefore, has 4 extra bytes on top. As far as I know, this is pretty standard. I tested this and took advantage of this fact before doing a load on a place from a binary file with fixed vtbls. Over the past 6 months, I have been working in Xcode and most recently faced the need to do some downloads in place, so I studied the vtbls fixes again. To make sure my understanding is correct, I wrote a sample program. Here he is:

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

My expected result:

A: 8

Data: 1

B: 12

Data B: 4

C: 16

Data C: 8

world

D: 8

However, the conclusion I get is:

A: 16

Data: 1

B: 16

Data B: 4

C: 24

Data C: 8

world

D: 8

Does anyone know what is going on here? Thanks!

+1
source share
1 answer

AC class instances contain vptr, a pointer to a virtual function table for a dynamic type. This pointer occupies 8 bytes on your 64-bit machine (or 4 bytes on a 32-bit machine). Each int member takes 4 bytes.

The minimum sizeof (Class) is the sum of sizeof (member) for all members. If so, then

 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 

However, this is only a minimum size. Compilers usually increase this size to a multiple of sizeof (void *), which is 8 bytes here. This process is called aligning . It might seem like a memory scare, but it is outweighed by the performance gain: the CPU can read aligned data much faster than non-aligned data.

By the way, your expected result would be correct if you were on a 32-bit machine. Pointers (esp. Vptr) are 4 bytes wide, and alignment also multiplies by 4 bytes. Since all data members of the classes in question are 4 bytes in size, nothing will be aligned there.

+3
source

Source: https://habr.com/ru/post/1494989/


All Articles