CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 28
  1. #1
    Join Date
    May 2011
    Posts
    8

    sizeof() class with empty base class

    Hello all,

    I'm attempting to write some portable code between VC++ and GCC. However, GCC is generating something different and unusable for me without fundamental changes to what I want to do. I have the following hierarchy:
    Code:
    class Base
    {
        // helper functions here
    };
    
    class Vector4 : public Base
    {
        float x, y, z, w;
    };
    
    class Matrix4x4 : public Base
    {
        Vector4 rows[4];
    };
    
    int main()
    {
        printf( "sizeof( Matrix4 ) = %i\n", (int)sizeof( Matrix4x4 ) );
        return 0;
    }
    VC++ outputs 64.
    GCC outputs 68.


    I've tried GCC versions 4.3.4 and 4.5.2, and experimental 4.6.1 and 4.7.0 and they all produce 68.

    At first glance you'd think the correct output is 64, but I could be missing some loop-hole rule in the C++ standard that allows GCC to inflate the size of the class in such a way.

    Removing the base class in either 'Vector4' or 'Matrix4x4' fixes the problem. However, I plan on adding helper functions to 'Base' class that I want accessible from both the child classes. And 'Base' will remain empty of member variables.

    Do you all think this is correct behavior or should I post a GCC bug to their database? Or am SoL because the C++ standard doesn't care.

    Thanks.

  2. #2
    Join Date
    May 2011
    Posts
    8

    Re: sizeof() class with empty base class

    Forgot to mention that both VC++ and GCC output: sizeof(Vector4) = 16
    Hooray.

  3. #3
    Join Date
    Dec 2004
    Location
    Ann Arbor, MI
    Posts
    281

    Re: sizeof() class with empty base class

    My guess is it has to do with a difference in if / when / how those compilers generate vtables. AFAIK that implementation detail is not covered in the C++ standard.

    Why does this affect what you want to do?
    --EJMW

  4. #4
    Join Date
    Aug 2008
    Posts
    902

    Re: sizeof() class with empty base class

    Notice that it occurs only when both Vector4 AND Matrix4x4 inherit from Base.

    Why exactly do you need inheritance in this situation? When are you going to need a heterogeneous Base* container of Vector4s and Matrix4x4s? That wouldn't make any sense.

    Edit: Also, judging by the names, you intend to use these for graphics processing. I found out the hard way that a OO approach is generally detrimental to performance in this case. You are better off using one of the open source graphics math libraries, which have the advantage of using SSE.
    Last edited by Chris_F; May 26th, 2011 at 11:22 PM.

  5. #5
    Join Date
    May 2001
    Location
    Germany
    Posts
    1,158

    Re: sizeof() class with empty base class

    Why do you care about the class' size in the first place?

  6. #6
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: sizeof() class with empty base class

    When I see 'sizeof' in C++ code it usually means that it is about to solve a problem in a very 'C' like way. There may be a C++ idiom that you could use instead.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: sizeof() class with empty base class

    Quote Originally Posted by chopin952 View Post
    At first glance you'd think the correct output is 64,
    No. To any experienced C or C++ programmer, at first glance, the correct output is this:
    Code:
    sizeof(Matrix4x4);
    A programmer should never assume what the sizeof() a type is other than sizeof(char), which is guaranteed to be 1. Basing an application on sizeof(type) sounds like a design flaw. A compiler is free to make the sizeof() any user-defined type anything it wants it to be. A user-defined struct or class can have padding or different alignment that would cause different results -- even the same compiler can cause sizeof() to be different if compiled with different options.

    But if your design really needed a type to be sizeof() some specific number, then you should have coded it to make sure of this:
    Code:
    char tmp[sizeof(MyType) == 64)?1:0];
    Now the code will fail to compile if the compiler's sizeof(MyType) doesn't produce the numbers that you're looking for.
    Do you all think this is correct behavior
    Yes, the behaviour is correct.
    or should I post a GCC bug to their database?
    It isn't a bug.
    Or am SoL because the C++ standard doesn't care.
    The standard doesn't care, as long as the sizeof() is >= 1.
    but I could be missing some loop-hole rule in the C++ standard that allows GCC to inflate the size of the class in such a way.
    It has nothing to do with the compiler, and everything to do with the requirements of your application, which are rather restrictive.

    As to the standard, the standard only describes the sizeof() built-in types with respect to another built-in type. Nowhere does the standard give any concrete numbers as to what sizeof(x) must be (except for sizeof(char)).

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; May 27th, 2011 at 04:36 AM.

  8. #8
    Join Date
    Aug 2008
    Posts
    902

    Re: sizeof() class with empty base class

    Code:
    char tmp[sizeof(MyType) == 64)?1:0];
    Also, you could use:

    Code:
    static_assert(sizeof(Matrix4x4) == 64, "Error: sizeof(Matrix4x4) was not 64.");
    Since static_assert is supported now by both MSVC and GCC.

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: sizeof() class with empty base class

    Quote Originally Posted by Chris_F View Post
    Code:
    char tmp[sizeof(MyType) == 64)?1:0];
    Also, you could use:

    Code:
    static_assert(sizeof(Matrix4x4) == 64, "Error: sizeof(Matrix4x4) was not 64.");
    Since static_assert is supported now by both MSVC and GCC.
    Yes, that's true, but just in case the OP is willing to try on an older compiler, the char array version will work (or the boost equivalent of this will also work).

    Regards,

    Paul McKenzie

  10. #10
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725

    Re: sizeof() class with empty base class

    Quote Originally Posted by chopin952 View Post
    but I could be missing some loop-hole rule in the C++ standard that allows GCC to inflate the size of the class in such a way.
    .

    Actually, it is a loophole that allows the empty base class to occupy zero bytes.

    See http://www2.research.att.com/~bs/bs_...l#sizeof-empty

    In 2003 Standard : 10 Derived Classes, paragraph 5
    In draft of new standard : 10 Derived Classes, paragraph 8

  11. #11
    Join Date
    May 2011
    Posts
    8

    Re: sizeof() class with empty base class

    Thanks to Paul and others for your replies.
    Quote Originally Posted by Paul McKenzie View Post
    No. To any experienced C or C++ programmer, at first glance, the correct output is this: sizeof(Matrix4x4); A programmer should never assume what the sizeof() a type is other than sizeof(char), which is guaranteed to be 1. Basing an application on sizeof(type) sounds like a design flaw. ... A user-defined struct or class can have padding or different alignment that would cause different results.
    Ouch, but fair enough. I definitely understand alignment rules. I assumed though, that on the same architecture, two compilers that generate alignment compatible code would generate sizeof() compatible code. I'm obviously mistaken.

    Regarding sizeof(). I've found three relevant rules in the C++ Standard:
    Section 5.3.3: sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1. The result of sizeof applied to any other fundamental type is implementation-defined. ... When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array. The size of a most derived class shall be greater than zero.
    Section 9: Complete objects and member subobjects of class type shall have nonzero size. Base class subobjects are not so constrained.
    Section 10: A base class subobject may be of zero size.
    I understand that none that spells out exact sizing. However, since sizeof(Vector4)==16 and according to 5.3.3, the result of sizeof(Matrix4x4) is the number of bytes in that object including any padding, and according to 9/10 Base class is allowed to have zero size, then my real questions should have been:
    • Why is GCC adding an extra 4 bytes?
    • Where is the extra padding in the class layout?
    • Is it garbage values?
    • Is it adding a virtual table?
    • If I change Matrix4x4 to contain float[16] then the size becomes 64. Why is that any different than the Vector4 members?
    • If I make an array of Matrix4x4 with the empty base, does it now need extra padding versus Matrix4x4 without the empty base?
    • The alignment of these structures is 4. Why waste the memory? Why stop at 4? Why not add an extra 8, 12, 16, 28 bytes?

    I will do some experiments with reading/writing the 68 bytes to see what's in there.

    Re: Design. I don't actually need the derivation. It is merely for convenience of access to static functions in Base. I will never pass around Base pointers that represent vectors and matrices. As Stroustrup says in the link provided by Philip: "It allows a programmer to use empty classes to represent very simple concepts without overhead. Of course I could change it and simply make calls to those helpers using full qualification Base::XXX().

    Finally, I care about the size because I auto-generate custom RTTI for these classes to be used in a scripting language. The RTTI is generated on one platform and will be read-in by another. This is proving trickier by the moment and I may have to rethink some other concepts.

    Thanks all for your answers.

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449

    Re: sizeof() class with empty base class

    Quote Originally Posted by chopin952 View Post
    [list][*]Why is GCC adding an extra 4 bytes?
    Whatever the reason, it is still valid for the authors to do whatever they please, as long as they adhere to the standard.
    [*]Where is the extra padding in the class layout?
    Write a small program that prints out the addresses of each of the members.
    [*]If I change Matrix4x4 to contain float[16] then the size becomes 64. Why is that any different than the Vector4 members?
    Because arrays are guaranteed to be contiguous, while specifying discrete float variables are just that -- discrete float variables. One float value has no connection to another.
    Finally, I care about the size because I auto-generate custom RTTI for these classes to be used in a scripting language. The RTTI is generated on one platform and will be read-in by another. This is proving trickier by the moment and I may have to rethink some other concepts.
    Then if this is the case, you can either try to work out a better design, or if not, use the static_assert() that was mentioned to guarantee you don't produce builds that do not work correctly, and to determine exactly where the incompatible types occur at compile-time (instead of the program failing miserably at run-time).

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; May 27th, 2011 at 12:44 PM.

  13. #13
    Join Date
    Jun 2003
    Location
    Armenia, Yerevan
    Posts
    720

    Re: sizeof() class with empty base class

    I'd rather use std::vector, pretty much suited for the most cases related with contiguous memory represantation.
    Code:
    std::vector<4, std::vector<float>(4)> mat4x4;

  14. #14
    Join Date
    Aug 2008
    Posts
    902

    Re: sizeof() class with empty base class

    Quote Originally Posted by AvDav View Post
    I'd rather use std::vector, pretty much suited for the most cases related with contiguous memory represantation.
    Code:
    std::vector<4, std::vector<float>(4)> mat4x4;
    vector is primarily for arrays of dynamic length. Your Matrix4x4 will always be the same dimensions.

    You could use std::array<std::array<float,4>,4> or simply float[16].

  15. #15
    Join Date
    Jun 2003
    Location
    Armenia, Yerevan
    Posts
    720

    Re: sizeof() class with empty base class

    Or float[4][4]

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured