4

Possible Duplicate:
Why does ‘sizeof’ give wrong measurement?

I have a structure called CBUFFER_PEROBJECT:

struct CBUFFER_PEROBJECT
{
    D3DXMATRIX Final;
    D3DXMATRIX Rotation;
};

And in another class I do this:

...
bd.ByteWidth = sizeof(CBUFFER_PEROBJECT); 
...

I found out that the size of D3DXMATRIX is 64, so 64+64 = 128 (right?). But my compiler is playing tricks with me (Visual C++), because as I was debugging the program, the bd.ByteWidth became 132, so I went to the Immediate Window (Visual Studio), and typed:

sizeof(D3DXMATRIX) + sizeof(D3DXMATRIX)

And the result was:

128

But the bd.ByteWidth became 132, and when I type the following into the "Immediate Window":

sizeof(CBUFFER_PEROBJECT)

It gives me:

128
Community
  • 1
  • 1
Miguel P
  • 1,262
  • 6
  • 23
  • 48
  • 64 + 64 is 128, based on the question, 64 + 64 is what's probably intended. –  Dec 27 '12 at 18:31
  • 5
    Depending on your compiler settings you could get padding on structs/classes...You can also get added in the size of a pointer to a vtable, etc. – Todd Murray Dec 27 '12 at 18:31
  • `CBUFFER_PEROBJECT` won't have a vtable. – Lightness Races in Orbit Dec 27 '12 at 18:32
  • 2
    post a complete but minimal program that demonstrates the problem – Cheers and hth. - Alf Dec 27 '12 at 18:33
  • Looks like a compiler bug from what you've told us. Try making a minimal example that exposes it. – dupersuper Dec 27 '12 at 18:33
  • Are you sure that `bd.ByteWidth` is set to `132` by *this specific line*? It's possible that it's overwritten to 132 by some stray out-of-bounds memory write. You can compile with the `/d1reportAllClassLayout` flag to see the layout of that specific structure as the compiler builds it, but the fact that immediate `sizeof()` doesn't match the runtime result speaks against padding, IMO. – DCoder Dec 27 '12 at 18:39
  • @BoPersson: would that explain why the sizeof in the code produces 132 but the same sizeof expression in Immediate Window produces 128? – DCoder Dec 27 '12 at 18:45
  • @DCoder - I don't know how the compiler computes the size for different settings, just that `sizeof(struct)` is not required to be the sum of the sizes of the member fields. – Bo Persson Dec 27 '12 at 18:50
  • I would trust the compiler more than the debugger for size information. I assume there is some problem happening that brought about this question. What is that problem? If you are seeing different sizes in different translation units, then check the #pragma setting in effect. Visual C++ has #pragma's that change struct packing rules, which can change the size of a struct. – brian beuning Dec 27 '12 at 18:52
  • Well the real problem is that the size has to be a multiple of 16, because I'm working with shaders... – Miguel P Dec 27 '12 at 18:54
  • Don't believe the description is 100% correct (user error is more logical explanation). Provide a piece of code that we can compile that generates the said output. – Martin York Dec 27 '12 at 19:00
  • Voting **against closing as duplicate**. According to the description, the problem is a discrepancy between compiled `sizeof` and debugger-sizeof, which is different from the suggested duplicate question. (If the problem turns out to be an artifact caused by an error on the part of the questioner, the question should later be closed as localized.) – jogojapan Dec 28 '12 at 01:35

5 Answers5

6

Right, you are confusing D3DMATRIX and D3DXMATRIX (note extra X in the second type). The first one is a plain matrix of 16 float values (so exactly 64 bytes). The latter is a class, and it obviously has 4 bytes of extra data somewhere in the structure. Perhaps a vtable or some such.

If you compile the code as C rather than C++, the size will be the same, as the header-file providing the latter of the structures then does typedef D3DMATRIX D3DXMATRIX;.

See: D3DXMATRIX and D3DMATRIX

Edit: This is a bit like the old joke about the military saying "If the map and reality doesn't match up, the map is right". In this case, if you don't agree with the compiler, you are wrong. The compiler is ALWAYS right when calculating sizes. Understanding WHY the compiler got that number, well, that's a different matter... Usually resolved by comparing the expected offsets into the structure with what actually happens, and understanding what, if anything caused the "gaps".

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 4
    Where is the D3DMATRIX used in the code? – dupersuper Dec 27 '12 at 18:37
  • It isn't. D3DXMATRIX is - but since it is a class, it is a plausible explanation for taking up extra space. At least in my experience. – Mats Petersson Dec 27 '12 at 18:40
  • 1
    A more plausible explanation is structure alignment. – Soup d'Campbells Dec 27 '12 at 18:46
  • 2
    Why is that more plausible - 64 bytes of data followed by 64 bytes of data doesn't need 4 bytes of alignment anywhere. – Mats Petersson Dec 27 '12 at 18:52
  • It's not just 64 bytes. D3DXMATRIX is a complex type. You have to account for the internals as well. – Soup d'Campbells Dec 27 '12 at 19:43
  • Furthermore, this is Direct3D we're talking about, so I'm practically positive that they're using their own structure alignment rules (via #pragma) – Soup d'Campbells Dec 27 '12 at 19:51
  • That's what I'm trying to say, it's a complex type, so it will have other stuff in it, and D3DXMATRIX is not the same as the plain struct of D3DMATRIX, which should be 64 bytes. – Mats Petersson Dec 27 '12 at 21:32
  • D3DXMATRIX is inherited from D3DMATRIX and has no data members of its own. A vtable would be a plausible explanation if D3DMATRIX were a full class that exported functions, but it's not, and it wouldn't account for 4 bytes from 2 structures (that's two 2-byte vtable pointers). – Soup d'Campbells Dec 27 '12 at 22:08
  • Ok, so now I'm lost for explanations... But either way, the answer is that the compiler does what it thinks best, given the options/information given. – Mats Petersson Dec 27 '12 at 22:10
  • Additionally, if, at runtime, sizeof(D3DXMATRIX) == 64 && sizeof(CBUFFER_PEROBJECT) == 132, then the 4 extra bytes are clearly associated CBUFFER_PEROBJECT. OP would have to confirm this, but I find it to be a far more likely possibility than sizeof(D3DXMATRIX) == 66 – Soup d'Campbells Dec 27 '12 at 22:12
  • Absolutely. Always trust the compiler. Don't mean to be busting your balls, because you're spot on about that. :P – Soup d'Campbells Dec 27 '12 at 22:13
2

You can't calculate structure's size just counting it's members sizes, because in structures it is stored also some extra information (not visible for a programmer). That is why you get 132 instead of 128.

nabroyan
  • 3,225
  • 6
  • 37
  • 56
2

Sometimes when compilers are evaluating structure declarations, they will add bytes of padding between fields. This is because some types perform better when aligned to memory addresses that are multiples of their length.

I'd go so far as to say it's very likely that you would not see this effect in the immediate window.

Given these grounds, this is a duplicate question. You can get a more in-depth answer here: Why isn't sizeof for a struct equal to the sum of sizeof of each member?

Community
  • 1
  • 1
Soup d'Campbells
  • 2,333
  • 15
  • 14
1

In this case it's best to assume that the compiler is correct. What this most likely means is that you have two different definitions of CBUFFER_PEROBJECT in your project with slightly different definitions. The compiler thinks that definition A has size 132 while the debugger is looking at definition B with size 128. You can test this by creating global variables containing the value of sizeof(CBUFFER_PEROBJECT) in each source file. You can then inspect these globals in the debugger to see what it shows.

Another possibility is of course that your memory is getting overwritten and NOT set by the line you think is setting it. In that case, something like Purify or valgrind can help you track down the memory problem.

Mark B
  • 95,107
  • 10
  • 109
  • 188
1

You can use the hidden visual studio compiler switch to /d1reportSingleClassLayoutSomeType to tell you what the compiler layout is. Follow the link to read how to use the switch.

I tried it for your sample code but I don't have the type 'D3DXMATRIX'. I do have 'D3DMATRIX' so I tried that and got:

1>  class CBUFFER_PEROBJECT size(128):
1>      +---
1>   0  | _D3DMATRIX Final
1>  64  | _D3DMATRIX Rotation
1>      +---

So if you use the switch is should be able to tell you the exact layout of your struct.

Shane Powell
  • 13,698
  • 2
  • 49
  • 61