Sign in to follow this  

Struct alignment (VC2005)

This topic is 3739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, hopefully a simple question: How do you align structs in VC2005? I'm trying to align my matrix class to a 16-byte boundary. My matrix class is defined as:
#pragma warning(disable:4324) // 'Foo' : structure was padded due to __declspec(align())
__declspec(align(16)) class EMatrix
{
   // ...
};

And I have an EMatrix as a member of my model class:
class EModel : public ESceneObject
{
   // ...

protected:
   EID m_id;
   EVector3 m_vBoundingBoxMin;
   EVector3 m_vBoundingBoxMax;

   EMatrix m_matTransform;

   // ...

However, when I come to use the model's transform matrix, it's address is 0x011ea468, which obviously isn't 16 byte aligned. The D3DX version, D3DXMATRIXA16 uses the __declspec(align) modifier every time a matrix is defined: typedef __declspec(align(16)) _D3DXMATRIXA16 D3DXMATRIXA16, *LPD3DXMATRIXA16; Is there any way to avoid doing that? It just seems a bit odd that I have to mark the matrix as 16-byte aligned in the class header, and also wherever it's used. And what does marking the class as aligned in the class header do? The MSDN says "This type now has a 32-byte alignment attribute, meaning that all instances must start on a 32-byte boundary." (align(32) in their example). That's clearly not the case here. Cheers, Steve

Share this post


Link to post
Share on other sites
Ok, it looks like it's because my EModel class instance is allocated with operator new. Is there any way to gat around this? The EMatrix class instance is a member of the EModel class, and the EModel class is allocated on the heap.

This is looking like there's no way around it...

Share this post


Link to post
Share on other sites
I can't overload new for EMatrix, because that'll only have an effect if I create the matric on its own and not if it's a member of another class.
I don't really want to overload new for my EModel class, because then I have to do that for every class that contains a matrix, which is exactly what I want to avoid.

Share this post


Link to post
Share on other sites
Works fine in this little test app. Both Matrices were aligned. I set the alignment in the vcproject file to be 4 and 8 and it made no diff


__declspec(align(16)) class Matrix
{
long l1;
long l2;
long l3;
long l4;
};

__declspec(align(4)) class Number
{
long l1;
};

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
Matrix oMatrix1;
Number oNumber1;
Matrix oMatrix2;
Number oNumber2;

cout << "Matrix 1: " << hex << &oMatrix1 << endl;
cout << "Number 1: " << hex << &oNumber1 << endl;
cout << "Matrix 2: " << hex << &oMatrix2 << endl;
cout << "Number 2: " << hex << &oNumber2 << endl;

unsigned char ucTemp;
cin >> ucTemp;


return 0;
}





Edit however




__declspec(align(16)) class Matrix
{
long l1;
long l2;
long l3;
long l4;
};

__declspec(align(4)) class Number
{
long l1;
};

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
Matrix oMatrix1;
Number oNumber1;
Matrix oMatrix2;
Number oNumber2;

cout << "Matrix 1: " << hex << &oMatrix1 << endl;
cout << "Number 1: " << hex << &oNumber1 << endl;
cout << "Matrix 2: " << hex << &oMatrix2 << endl;
cout << "Number 2: " << hex << &oNumber2 << endl;

Matrix* pMatrix1 = new Matrix();
Number* pNumber1 = new Number();
Matrix* pMatrix2 = new Matrix();
Number* pNumber2 = new Number();

cout << "Matrix 1: " << hex << pMatrix1 << endl;
cout << "Number 1: " << hex << pNumber1 << endl;
cout << "Matrix 2: " << hex << pMatrix2 << endl;
cout << "Number 2: " << hex << pNumber2 << endl;

unsigned char ucTemp;
cin >> ucTemp;


return 0;
}



new aligned everything to 8 per vcproj settings

Share this post


Link to post
Share on other sites
Use _aligned_malloc() and _aligned_free() instead of new/delete.
For example,
Matrix* pMatrix = (Matrix*)_aligned_malloc(sizeof(Matrix), 16);
...
_aligned_free(pMatrix)

Share this post


Link to post
Share on other sites
In Windows (I am unsure of other platforms) New will always align only on a boundry of the largest type, ie 8 bytes for 32 bit platforms, no matter what you do to it. It all falls down to the win32 HeapAlloc function, so you can use malloc with placment new -- I think thats what it is called -- example:

void *pointer = malloc(sizeof(EMatrix)+16);
EMatrix *matrix = new((pointer+16)&(~15)) EMatrix;

// Should most likely only free pointer
matrix->~EMatrix();
free(pointer);








I also can't recall what it is named but there is a version of malloc that will align for you, but it does this exact same thing inside. -- EDIT: _aligned_malloc() thats what it was songho reminded me.

Of course you could do the same thing with just allocating two EMatrix classes with new and move the pointer the same way, although that will really F your destruction, etc, So i recommend against it.

Anycase sorry for the bad news that alignment stuff is so missleading in the documentation. It only guarantees that the structure will align to 16 bytes within the class, so once you throw new at it everything is out the window.

[Edited by - Wolfdog on September 18, 2007 10:23:20 AM]

Share this post


Link to post
Share on other sites

This topic is 3739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this