1

I have a confusing behaviour with the memory alignment of structure elements. Consider these two structures:

typedef struct s_inner {
    unsigned long ul1;
    double        dbl1;
    fourth_struct s4;
    unsigned long ul2;
    int           i1;
} t_inner;

typedef struct s_outer {
    other_struct    member1; /* 4-byte aligned, 40 bytes in terms of sizeof() */
    unsigned long   member2;
    t_inner         member3; /* see above */
} t_outer;

When I inspect the memory layout of t_outer, I could see that the elements of member1 are 4-byte aligned, just as I would expect it. Also the memory layout of member3 is as expected: ul1 has 4 padding bytes attached so that dbl1 is aligned on an 8-byte border (normal on Win32).

However, when I inspect the memory layout of member2, I could see that this member has 4 padding bytes attached to it. Could anyone explain why on earth member2 receives padding bytes? My expectation was that member2 does not carry a padding.


Edit 1: See this memory dump. Before filling the structure elements, I've memset'd the whole t_outer structure with p's:

  • the red area is member1
  • the blue area is member2
  • the green area is member3
  • the yellow area marks the location of dbl1 within member3

memory-layout


Constraints

  • Compiler is VS2012
  • the actual stucture of other_struct should not matter here, it's a 40-byte sized 4-byte aligned structure
  • I do not want any workarounds for the behavior (reordering, packing, ...) but an explanation why this is happening.
3
  • What is "other_struct" ? Commented Jan 8, 2015 at 14:04
  • Padding is inserted at the discretion of the compiler, so which compiler are you using? Commented Jan 8, 2015 at 14:13
  • Can you clarify where the padding is? Before or after member2. Commented Jan 8, 2015 at 14:14

2 Answers 2

2

so that dbl1 is aligned on an 8-byte border

Sure. But that alignment guarantee means bupkis if the structure itself is not aligned to 8 as well. Which is a guarantee that's normally provided by the compiler's address choices for the data section and the stack frame. Or the memory allocator. All guarantee at least alignment to 8.

But when you embed the structure inside s_outer then those 4 bytes of padding before member3 (not after member2) are required to get the alignment guarantee back.

Also note that a structure can have padding after the last member. Which may be required to ensure that members are still aligned when the structure is stored in an array. Same reason.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the clarification. One addon: the green area after the double seems no longer to be aligned. I assume that the alignment has to be kept to 8 until all doubles of the structure were read and then pop to 4. Is this correct?
No idea what you mean, looks aligned to me and I see only one double. We can't see "fourth_struct".
"I assume that the alignment has to be kept to 8 until all doubles of the structure were read and then pop to 4. Is this correct?" No, it is not correct. The VS docs don't actually specify the behavior precisely in that area, but given a sequence of members of types double, int, int, double, it is consistent with the VS docs for the second int to be aligned on a 4-byte boundary (and that's how I predict it would be aligned).
@JohnBollinger: I've opened a new question on this issue: stackoverflow.com/q/27858493/520162
2

The VS2012 docs describe its padding behavior. In particular, they specify that the alignment requirement for a struct is the largest alignment requirement of any of its members. Member member3's type t_inner has a member of type double, with an 8-byte alignment requirement, therefore member3 overall has an 8-byte alignment requirement (and, also, t_outer has an 8-byte alignment requirement). Padding is required between member2 and member3 to obtain 8-byte alignment of member3.

2 Comments

Sounds reasonable. The 8-byte alignment of t_outer and member3 do not affect the alignment of member1, right?
Well, there's no direct implication for member1, but because it's the first member of t_outer, t_outer requires 8-byte alignment, and VS2012 lays out members in declaration order, member1 will always be aligned on an 8-byte boundary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.