tags:

views:

291

answers:

6

I have a class that goes like this:

class myType
{

  union {
      float data[4];
      other_vector4_type v
  } ;
  typedef union {
      float data[4];
      other_vector4_type v
  } myType-internal_t;

 <various member functions, operator overloads>

}

Now I want to use this type in my vertex buffer, but the sizeof() isn't as expected. I aligned the class to 16 bytes.

sizeof(myType) yields 64.

sizeof(myType::myType-internal_t) yields 32.

I've read quite a few articles on data alignment but I don't know where I'm using extra data. I tried stripping out the custom constructor but it remains the same, swapping the class keyword for struct doesn't change it either (I don't understand what it's for, as it happens!)

This is annoying, I'll use the internal type for now since I won't be touching the data often, but it would be great to have the class work like I want.

+2  A: 

A C++ compiler can make that struct 128 bytes for all it cares. The size of structs/unions is not defined by the C++ standard. However, most compilers have a nonstandard __PACKED attribute you can add to the declaration of a struct and it will take up only the exact amount of bytes that it needs

Earlz
There will usually by a cost associated with packing. There is a reason you need to explicitly add the attribute. So you should only use it if there is some reason you need to remove all the padding (ie align it with some internal kernel structure, or a packet for on the wire transport).
Martin York
+1  A: 

If you have virtual functions in your class it will make your objects bigger than the internal type because of the vtable pointer.

BTW "struct { " is just the same as saying "class { public : "

siukurnin
thanks siukurnin!
Sorlaize
+1  A: 

I imagine you will have a vtable pointer defined for your objects. Either because you have RTTI enabled or any virtual method (including the destructor) will add a vtable

http://en.wikipedia.org/wiki/Virtual_method_table

Typically, the compiler creates a separate vtable for each class. When an object is created, a pointer to this vtable, called the virtual table pointer or vpointer, is added as a hidden member of this object (becoming its first member unless it's made the last[2]). The compiler also generates "hidden" code in the constructor of each class to initialize the vpointers of its objects to the address of the corresponding vtable.

epatel
+1  A: 

I just compiled

#include <xmmintrin.h>
#include <iostream>

struct myType
{
    union {
        float data[4];
        __v4sf v;
    };
    typedef union {
        float data[4];
        __v4sf v;
    } myType_internal_t;
};

int main() {
    std::cout << sizeof(myType) << std::endl;
    std::cout << sizeof(myType::myType_internal_t) << std::endl;
}

And the result is:

16
16

using gcc on a 64 bit arch. As expected. "__v4sf" is a vector type consisting of four floats. So the problem is probably in your "other_vector_4_type". Maybe it is polymorphic and virtual and contains two vtables? And you are using more virtual functions in "myType" which increase its size further? The problem may be related to your compiler or the architecture too.

drhirsch
A: 

Nope, I don't have a vtable pointer, nothing virtual. I read about a tool to dump object layout data, is there a good free one?

Sorry, forgot to add that I'm using vc++2008 express. I tried wrapping it in a struct, no changes.

@bmargulies and Charles Salvia- irrelevant as I'm getting 32 for the internal struct, no? :P

The problem I face is that the class is somehow adding an overhead to the struct (which works fine, in debug I can see the data and modify it as I like)

@jalf- aha, it was _ but _i starts italics.

drhirsch, thanks, I am using 64bit but compiling for win32, here is what I have now:

class myType
{
public:
    union {
        float data[4];
        other_vector4_type v;
    };
    typedef union {
        float data[4];
        other_vector4_type v;
    } myType_internal_t;
};

And I am getting 32 (16 for the above sample) (I should have mentioned, I'm checking size of myType*2 and another type that has 2 of them.)

So I was initially right, my class is adding some overhead to it, but it's not virtual and doesnt inherit from anything! So the answer lies in the methods I'm using..

Sorlaize
well it started italics in the preview window, hah.
Sorlaize
Did you read my answer? I'm sure that MSVC has a `__packed__` attribute somewhere in it.. Try using that and seeing if that resolves it. Also, why must you have an exact size? And we need the `other_vector4_type` to understand your problem better.
Earlz
Are you saying there's a way to declare my class as packed? Can't find a __packed keyword or similar, I want it to be this size so it directly maps to float4's on the gpu. Like I say here my vector4 type works exactly as I expect it to :P
Sorlaize
http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx `#pragma pack(..)`
Earlz
You should add updates like this to to your question by editing it rather than as an answer so that people considering your question don't have to search out all the information.
Michael Burr
thanks! I'll use it if I need to, I found a macro for it:http://stackoverflow.com/questions/1537964/visual-c-equivalent-of-gccs-attribute-packed
Sorlaize
OK - so you have a similar class that has the size you want. Why don't you add this information *and* the full declaration of the class you're having a problem with to your question so people don't have to try to **guess** what might be in there that's adding space? You've told us it's not virtual functions - why not just put the actual class declaration in the question so we might be able to see what it is? People on SO might be sharp, but as far as I know they aren't psychic.
Michael Burr
Michael, it was sensitive (commercial) code, so I did my best to show something with (what I was certain was) equally representative!
Sorlaize
@earlz- surely as I now have my 16 byte type, the alignment declaration I have is sufficient? I only care about x86/64 though.
Sorlaize
Ah - that makes for a bit of a dilemma. Sorry if I came across as a bit harsh. It looks like (unless you get lucky) you're best bet is to come up with a similar class that shows the problem but doesn't have the sensitive bits.
Michael Burr
Not always... Alignment is not the same thing as packing.. If you compile with optimizations, it may break..
Earlz
A: 

Well that's weird, it seems to work fine now (16 bytes with a custom ctor) so I'll search-and-destroy the culprit method !

Thanks for all the fast replies/help, you inspired me!

@Michael Burr- true, and I just noticed ajax updates comments.. this gives more impact though.

Sorlaize
No, it doesn't give more impact. I had to read all the way to the bottom of the page to see that you were in fact responding to questions. Since your responses aren't answers, nobody votes them up, so even the mediocre answers from others appear above your responses. Edit your question to add more details. Post comments to others' questions to ask for clarification. You're allowed to comment within your own question even though you still need higher reputation to comment elsewhere on the site. Welcome to Stack Overflow.
Rob Kennedy