Re:A bug story: data alignment on x86
by alkonaut on Monday November 07, 2016 @08:57AM
(#12890994)
Not sure if this is what you are asking: Last time I tried alignment in Rust I worked around the lack of explicit alignment support by adding a zero length array of the correct size to the end of the struct. Not sure if alignment support from proper attributes has landed yet.
where "EightBytes" is a data type of size 8, to align the whole struct on 8 bytes.
[ Parent
| on HN ]
Re:A bug story: data alignment on x86
by steveklabnik on Monday November 07, 2016 @09:34AM
(#12891240)
Structs already insert padding to give them alignment:
struct One {
foo: u8,
}
struct Two {
bar: u16,
}
struct Three {
foo: u8,
bar: u16,
}
struct Four {
foo: u16,
bar: u16,
}
fn main() {
assert_eq!(1, std::mem::size_of::<One>());
assert_eq!(2, std::mem::size_of::<Two>());
assert_eq!(4, std::mem::size_of::<Three>());
assert_eq!(4, std::mem::size_of::<Four>());
}What I needed to do was to place e.g. a N byte struct exactly on an M byte alignment (e.g. 11 byte struct on 32 byte alignment etc).
Re:A bug story: data alignment on x86
by steveklabnik on Monday November 07, 2016 @10:10AM
(#12891616)
Ah! Yeah, that's different, and as far as I know your way is the current right way to do it, but I'm not an expert on the subject.
Well given that Rust leaves struct layout undefined unless #[repr(C)] is specified, std::mem::size_of::<Three> is actually not guaranteed to be 4.
Re:A bug story: data alignment on x86
by steveklabnik on Monday November 07, 2016 @02:01PM
(#12893824)
While this is true, it's a weird angle that's not itself super well defined. That is, the definition of repr(packed) implies that the alignment will always be there without it...
I doubt you can count on all items being allocated at addresses that are multiples if their size.
It's not optimal but you can always use libc::posix_memalign()
The final element of the struct is a zero length array of elements of size N bytes. So that element isn't padding, it has size 0! It's pure hinting. I'm not sure why or how this works under the hood I'm afraid. I used it successfully to call a library with pretty strict alignment requirements (Intel Embree).
The zero length array still must be aligned correctly. You can create a pointer to it (e.g. by taking &something._alignment[..] to create a slice) and pointers must have correct alignment, so it follows that a zero length array has the same alignment requirements as a longer array. So padding must be inserted in your struct so that the address of the zero-length array is correctly aligned.
Hmm, I don't understand (sorry). The pointer to the internal array must be aligned. But how does the element size play into the padding. If we take these two examples?
[repr(C)]
struct StructA
{
pub foo: f32,
_alignment: [SixteenBytes, 0]
}
[repr(C)]
struct StructB
{
pub foo: f32,
_alignment: [ThirtytwoBytes, 0]
}
Are both just padded with 16-4 and 32-4 bytes respectively, so they are equivalent to making a padding like this in the first case? [repr(C)]
struct StructAPadded
{
pub foo: f32,
_padding : TwelveBytes;
}