2

As per the title. I don't really want to list all the other members it contains but I was suprised to find that given the only non-static data members were the enum, 2 of int and a pointer to its own type that its sizeof should be 20.

It has no virtual functions and I've measured the pointer and enum as 4 bytes each. Should I look harder for other members?

I need this information to allocate a buffer for n objects of its type when reading back in from a file.

Platform: bada, Environment: gcc and Eclipse in Win 7 x64.

enum blockParams {enum1, enum2, /**/};
class Block : public Object {
public:
    int begin;
protected:
    Block() : begin(-1), end(UNCLOSEDBLOCK) {}
    //Last index
    int end;
private:
    blockParams1 params;
    const Block *parentBlock;
//Lots and lots (~80) member functions and static data members.
}
John
  • 6,433
  • 7
  • 47
  • 82
  • 1
    What platform? 32-bit/64-bit? Can you use a debugger or some similar tool to dump the fields' byte offsets? – reuben Feb 19 '12 at 23:30
  • What's your platform? And what does the actual code that specifies the class look like? – David Schwartz Feb 19 '12 at 23:31
  • possible duplicate of [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) – Mahmoud Al-Qudsi Feb 19 '12 at 23:31
  • 1
    Can you post the actual code please? – Kerrek SB Feb 19 '12 at 23:31
  • Depending on the environment, there may be compiler pragmas that you can use to control the layout (in addition to shuffling the fields)--of course, potentially introducing performance trade-offs. – reuben Feb 19 '12 at 23:31
  • Platform: bada, Environment: gcc and Eclipse in Win 7 x64. – John Feb 19 '12 at 23:36
  • This is answered by [the C++ SO FAQ](http://loungecpp.wikidot.com/faq#padding), please read it before asking a question about C++ – Seth Carnegie Feb 19 '12 at 23:36
  • @SethCarnegie: It seems non-sensical to pad 32 bit aligned members when the platform is as resource constrained as a mobile phone. – John Feb 19 '12 at 23:39
  • @John Nonsense. It makes perfect sense to pad, because mobile processors are *exactly* the kind of CPUs that will either fault or completely slow down when performing unaligned memory access. – Mahmoud Al-Qudsi Feb 19 '12 at 23:40
  • This data type is NOT *standard layout* (due to a mixture of public, protected, and private non-static member variables), so you cannot make assumptions about how members will be arranged in memory. – Ben Voigt Feb 19 '12 at 23:42
  • It's the inheritence from `Object` isn't it? – John Feb 19 '12 at 23:45

4 Answers4

6

The compiler is free to introduce padding between members to achieve various alignment requirements.

Many compilers offer a non-portable way to pack the structure more tightly (e.g. GCC's __attribute ((packed))), but there's seldom a good reason to use this.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • I was about to guess it might be 4 bytes for a pointer `this` member that might not apply in the C language (where I first found `sizeof`). So I can't really rely on `sizeof` for (de)serialization then? – John Feb 19 '12 at 23:31
  • @John: It sounds like you are "deserialising" by simply freading binary data from a file directly into the struct. This is a bad idea for exactly this kind of reason. It's also a bad idea because you are using pointers. – Oliver Charlesworth Feb 19 '12 at 23:32
  • Actually the pointers are to members of an array and I x-reference them with element indices in the containing class, which is why I was missing the 4 byte difference initially. I can't imagine any need for it to introduce a fifth DWORD. 16 bytes in 4 4 byte objects should be compilers' idea of heaven. – John Feb 19 '12 at 23:44
5

When I see a base type named Object, I really doubt the claim that there are no virtual functions.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Woohoo, well spotted, maybe I can clean up those 80 pithy one liners now virtual functions are not going to detriment caching. Completely forgot being required to inherit from `Object` for the sake of the _platform_. – John Feb 19 '12 at 23:47
1

If you use sizeof correctly, you do not need to know the size of the struct, the compiler will calculate your buffer size correctly for you.

The size of 20 probably includes padding the compiler adds for efficiency.

Steve Fallows
  • 6,274
  • 5
  • 47
  • 67
0

The size is the sum of the parts + padding.

int main()
{
    std::cout << "Object:       " << sizeof(Object) << "\n";
    std::cout << "int:          " << sizeof(int) << "\n";
    std::cout << "blockParams1: " << sizeof(blockParams1) << "\n";
    std::cout << "Block*:       " << sizeof(Block*) << "\n";

    int estimatedSize = sizeof(Object) + (2 * sizeof(int)) + sizeof(blockParams1) + sizeof(Block*);
    int actualSize    = sizeof(Block);

    std::cout << "Block:        " << actualSize << "\n";
    std::cout << "Padding + implementation defined data for virtual functions:      " <<  (actualSize - estimatedSize) << "\n";
}

Running this with Object just being empty:

> ./a.out
Object:       1 // Note: This may be optimized away in Block.
                //       All objects must have non 0 size but when they are a base class
                //       you can optimize an actual zero sized object away.
int:          4
blockParams:  4
Block*:       8
Block:        24
Padding + implementation defined data for virtual functions:      3
// Note because the Object size 1 will be optimized away this is actually 4.

Running this with object containing a virtual destructor

> ./a.out
Object:       8
int:          4
blockParams:  4
Block*:       8
Block:        32
Padding + implementation defined data for virtual functions:      4
// Note It will use the area in Object for virtual functions so it does not
//      Explicitly need any itself (in this implementation using a vtable).

If we assume pointers on your platform are 4 bytes (and you have Object with virtual functions). I would expect to see:

> ./a.out
Object:       4
int:          4
blockParams:  4
Block*:       4
Block:        20
Padding + implementation defined data for virtual functions:      0
Martin York
  • 257,169
  • 86
  • 333
  • 562