How to do proper alignment in structs?

If I create or add a member to a struct in a DNA_*.h file I will usually get alignment error. Apparently, two aspects of alignment must be dealt: position of padding within the struct and number of bytes within the padding array. So far, I’ve had to use the trial and error method to find out when my padding resolves the problem. This, however, is tedious.

Question: What is the common way to find out where padding should go, and how many bytes should the padding array contain ?

Question: Is the alignment error below actually instructing the proper location and number of bytes for proper padding, and if so, can you explain the instructions ?
.

7>Align 4 error (32 bit) in struct: TreeFilterElement i (add 1 padding bytes)
7>Align 4 error (64 bit) in struct: TreeFilterElement i (add 1 padding bytes)
7>Align 2 error (32 bit) in struct: TreeFilterElement s (add 1 padding bytes)
7>Align 2 error (64 bit) in struct: TreeFilterElement s (add 1 padding bytes)
7>Sizeerror 4 in struct: TreeFilterElement (add 3 bytes)
8>mask_add.c
8>mask_draw.c
8>mask_edit.c
8>mask_ops.c
8>mask_relationships.c
8>mask_select.c
7>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(209,5): error MSB6006: "cmd.exe" exited with code 1.
7>Done building project "bf_dna.vcxproj" -- FAILED.

Here is my test struct that I’d like to understand:

…\blender\source\blender\makesdna\DNA_outliner_filter_types.h

typedef struct TreeFilterElement {

   char c;
   //char c2[3];
   int i;
   //char c3[2];
   short s;

} TreeFilterElement;

AFAIK you only need to use padding to ensure that the total size of the structure is a multiple of 8 bytes. So to make it is exactly 8, 16, 24, 32, 40, 48, etc. I have never come across a time when the position of the padding made any difference.

But someone might correct me if I’m wrong…

Hmm. I tried adding char array elements one at a time per rebuild and I simply could not get an error free build until I actually tested changing positioning of padding. It meant the difference between error and no error. So I don’t know what that was about. Of course, this was for struct SpaceOutliner

Yes, there is some quasi-inheritance there. All the “space*” structs start with the stuff that is in the struct SpaceLink, which itself has padding. So you can’t piss around with the stuff in there - until after the “End ‘SpaceLink’ header” comment. So don’t touch the header and just add/remove padding after that to align it all to 8 byte boundaries.

1 Like

Actually I’m glad you told me that: good info. Still, I had added a few variables just before void *treehash; at the bottom when I got the errors.

I guess I’ll experiment more to make sure I’m just not overlooking something.

1 Like

Here is another error type, "Align pointer error ", that I don’t seem to be able to simply add padding and get proper alignment.

1>makesdna.vcxproj -> C:\BlenderSrc\build_windows_Full_x64_vc15_Release\bin\Debug\makesdna.exe
5>------ Build started: Project: bf_dna, Configuration: Debug x64 ------
2>bf_gpu.vcxproj -> C:\BlenderSrc\build_windows_Full_x64_vc15_Release\lib\Debug\bf_gpu.lib
6>------ Build started: Project: bf_collada, Configuration: Debug x64 ------
5>Generating dna.c, dna_type_offsets.h, dna_verify.c
5>Align pointer error in struct (size_native 8): TreeFilterElement *vp
5>Align pointer error in struct (size_64 8): TreeFilterElement *vp
5>Sizeerror 8 in struct: TreeFilterElement (add 4 bytes)
6>DocumentImporter.cpp
6>ExtraHandler.cpp
6>GeometryExporter.cpp
6>ImageExporter.cpp
5>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(209,5): error MSB6006: "cmd.exe" exited with code 1.
5>Done building project "bf_dna.vcxproj" -- FAILED.

Here is the struct example:

typedef struct TreeFilterElement {

   short s;
   void *vp;
   short s2;

} TreeFilterElement;

try

typedef struct TreeFilterElement {
   short s;
   char _pad1[6]; 
   void *vp; 
   short s2; 
   char _pad2[6];
} TreeFilterElement;

What about putting the two shorts next to each other:

typedef struct TreeFilterElement {
   short s;
   short s2;
   char _pad1[4]; 
   void *vp; 
} TreeFilterElement;

To save 64 bits per widget?

I’ve built passed the point of the previous errors and everything seems to be building fine.

Now, my original issue is/was how does one properly align? What should be taken into consideration?

Oriinally, I just thought that the structs had to be multiples of eight, but the example I gave shows more needs to be considered.

Would be better, but I figured it would be easier to grasp when I split the alignment of the pointer and the size requirements of the struct into two distinct pads.

makesdna will tell you when you did it wrong.

1 Like

So, is the error message that I listed produced by makesdna.exe rather than VS ? Or maybe you’re referring to makesdna.exe error logs?

If so, you wouldn’t happen to know how to interpret and apply the error message to properly correct for alignment - would you ?

Obviously, the error message tells me alignment is off, but I don’t know what to change from that point. It seems like there are usually three spots that typically may need padding for any one member addition or removal.

I’ve been checking out this website for info: https://jonasdevlieghere.com/order-your-members/

I’m not positive for all x86/x64 details, but in general in RISCy architectiures (or things like x86/x64 that have RISCy implementations these days) you want things to be aligned to match their size, so characters can be anywhere, shorts need to be at even byte addresses (multiples of 2), ints at a multiple of 4, and longs/pointers at a multiple of 8 (on an I32LP64 architecture/mode).

I don’t know how much Blender has separate cases for 32-bit builds or whether it just leaves the extra 64-bit padding in and it all works out automagically when pointers are only 4 bytes instead of 8.

Dodo knows I’m sure.

1 Like

Ohhhh… thanks for that. I did not realize that pointers needed alignment as well, but makes sense. I must have just been lucky when I’ve poked and prodded at things randomly.

That’s what I was reading. But I would like to get some professional advice on any details about how to make the process simpler and more intuitive. For one thing/problem, if you declare a struct member inside a struct, you have to somehow figure out how big the struct variable is, and that adds to the tediousness. Actually, it may be that my entire problem is just pointer related though. I may even simply need to just think about alignment a lil more. I’ll test tomorrow

This “Harleya” guy seems to be dispensing bad advice. LOL

I never look at advice or any information as being absolute anyway. I’m just glad to receive help

1 Like

Ok. I now know how to do proper alignment and padding within Blender. I’m planning on writing a little tutorial for others who might be interested. There are a number of useful and or necessary things to understand in order to do proper alignment.

After I get it wrote, I hope maybe some more experienced people can correct and add to it to improve it. I’m gonna shoot to have it included in the official documentation pages too (I know there’s already a struct alignment section, but I think it needs to be improved).

Reading an error message and fixing the problem needs a tutorial?

Don’t get me wrong, anyone wanting to write documentation i’m not gonna discourage,

but yikes…

A very small tutorial, yeah. I was mostly just planning on making a few modifications to the current documentation.

Well, consider, for example, I don’t remember the Blender documentation mentioning two dimensions of alignment. The entirety of the struct and also the individual members. That’s just one thing that needs to be addressed.

but makesdna tells you exactly what is wrong and how to fix it, even if you know none of the rules…

7>Align 4 error (32 bit) in struct: TreeFilterElement i (add 1 padding bytes)

Add one padding byte before i

7>Sizeerror 4 in struct: TreeFilterElement (add 3 bytes)

Add 3 padding bytes at the end of the structure.

the only thing confusing is that the 3 at the end, will be 2 once you fix the i alignment, but really… makesdna is doing a pretty good job at holding your hand here