Thursday, February 9, 2012

Structure alignment

One of the great things about working in the Real Studio environment is that a lot of the nitty gritty details are handled for you, and if you ever need to branch outside this environment you can with declares. However, one very important detail needs attention if you deal with declares, especially those that accept a Structure as a parameter.

By default Realbasic packs Structures, which means the Structure doesn't take up any more space then what you defined. For example, take this structure:


This is an example of a packed Structure, where the two members take up a total of 5 bytes. That's great if this Structure never leaves Realbasic land, but if you plan on using it in a declare for example, that's when you'll need to worry about Structure alignment. Depending on how the shared library was built, the Structure alignment could vary, but the common alignment strategy is to align to the largest integral type or to the natural alignment (i.e. 4-bytes for 32-bit or 8-bytes for 64-bit), whichever is less. On Windows you'll find that their OS APIs always align to the largest integral type. Here's an example of the difference:
struct {
     int a;    // RB Integer (4-bytes)
     double b; // RB Double (8-bytes)
     short c;  // RB Int16 (2-bytes)
}

The default Structure alignment would typically be 4-bytes if calling a 32-bit OS API on OS X and Linux so the Structure above would take up 16 bytes. This is how it looks in memory:

If calling a Windows OS API the Structure alignment would be aligned to the largest integral type, and in this case we have a double which is an 8-byte integral so the Structure above would take up 24 bytes. This is how it looks in memory:


Notice the automatic padding that happens, wouldn't it be nice if Realbasic padded the Structures too? Well it can, if you specify the StructureAlignment attribute on the Structure. The only thing you need to make sure of is that the alignment strategy that you want to use as Realbasic does not assume anything. To specify the Structure alignment just right-click on the Structure to bring up the Attributes editor and enter the StructureAlignment.


Now our Structure will be aligned on a 4-byte boundary, which means the first member is padded with 3 extra bytes:


As you can see, the Structure alignment strategy changes the memory layout of the Structure so it's very important to understand the alignment strategy of the shared library that you are calling, otherwise you can run into some random memory corruption issues.

No comments: