0

The below program when compiled using gcc and executed on a 32-bit architecture returns 16 bytes. I am wondering why it is returning so as it is neither uses a long double member nor it is running on a 64-bit machine and there is no virtual functions defined to get extra bytes of memory and when calculating the size of double and int data member, the result comes around 12 bytes. So why this 16 bytes value?

class A {
public:
     void* data;
};
void* operator new (size_t sz, A& obj) {
     printf("Custom operator new called for %d bytes\n", sz);
     return obj.data;
}
class foo {
public:
     double a;
     int x;
     foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
     A obj;
     obj.data = malloc(sizeof(foo));
     printf("Allocator data: %p\n", obj.data); // Allocator data:  0x4601a8
     foo *f = new (obj) foo; // Custom operator new called for **16 bytes**
                                       // foo constructor called (this=0x4601a8)
     printf("foo allocated at %p\n", f); // foo allocated at 0x4601a8
}
Ibrahim Quraish
  • 3,889
  • 2
  • 31
  • 39

5 Answers5

3

4 bytes are added at the end of foo as padding. This is typically done for alignment purposes - a double is aligned to 8 bytes on your architecture, so if you create an array of foos, the padding bytes guarantee that the member a is properly aligned.

In a class-type there's no guarantee that the size is equal to the sum of the sizes of members. More often than not, it isn't.

There are special compiler-dependent flags that prevent padding bytes being added which you can look up. (pragma pack)

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

There may be unnamed padding within a structure object, which is called Data_structure_alignment

in your case, double is aligned to 8 bytes, so the sizeof foo should be 8*N ,so 4bytes padded

michaeltang
  • 2,850
  • 15
  • 18
0

when i run your code i found following :

class A {
public:
     void* data;
};
void* operator new (size_t sz, A& obj) {
     printf("Custom operator new called for %d bytes\n", sz);
     return obj.data;
}
class foo {
public:
     double a;
     int x;
     foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
     A obj;
     obj.data = malloc(sizeof(foo));
     printf("Allocator data: %p\n", obj.data); // Allocator data:  0x991d008
     printf("size of obj: %d\n", sizeof(obj)); // size of obj:  4
     printf("size of foo: %d\n",sizeof(foo)); // size of foo: 12
     foo *f = new (obj) foo; // Custom operator new called for **12 bytes**
                                       // foo constructor called (this=0x991d008)
     printf("foo allocated at %p\n", f); // foo allocated at 0x991d008
} 

I have added two additional printing statement, here size of foo is 12. that is double + int.

rajenpandit
  • 1,265
  • 1
  • 15
  • 21
  • Padding is system-specific so this is unfortunately not that helpful. The code will give different results on different computers and compilers. – Lundin Feb 28 '14 at 07:36
0

This is because of internal padding applied by the compiler. We can avoid this by using __packed compiler directive.

You can refer the following post for understanding about padding

Structure padding and packing

Community
  • 1
  • 1
prince
  • 1,129
  • 1
  • 15
  • 38
0

Consider data alignment. Compiler aligns data of the object in oder to store them in memory so that CPU can get them in one load - this is possible only for aligned data. This is hardware aspect.

Spock77
  • 3,256
  • 2
  • 30
  • 39