9

I'm looking for a good (comprehensive) doc about memory alignment in C++, typical approaches, differences between compilers, and common pitfalls. Just to check if my understanding of the topic is correct and to learn something new.

This question is inspired by my answer to another question where I used following construct:

char const buf[1000] = ...;
unsigned int i = *reinterpret_cast<unsigned int*>(buf + shift); // shift can be anything

It was criticized as not conforming to memory alignment rules. Can you please explain as a bonus why this approach is flawed from memory alignment point of view? An example when it doesn't work will be highly appreciated. I know it's a bad approach in general, but I often use it in network protocol implementations, so it's more a practical question than theoretical one.

Also please don't mention strict-aliasing here, it's for another question.

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • Is shift not a multiple of your system's word size? You could have been criticized for trying to get a pointer in the middle of a word (say in the middle of a 32-bit word), which would be weird. – Doug T. Sep 06 '11 at 13:38
  • 1
    even if shift was a multiple of 4, there's no guarantee `buf` would start at an address being multiple of 4 – nos Sep 06 '11 at 13:40
  • `shift` can be anything, updated the question – Andriy Tylychko Sep 06 '11 at 14:03
  • 1
    I'd just like to note here that many compilers have - as a non-standard extension - alignment directives that can be used to set the alignment of structures to `1` - wrap your int in a 1-aligned structure, and you can indeed dereference at any offset safely. The overhead incurred depends on your CPU architecture; on x86 it should not be overly painful. – bdonlan Sep 06 '11 at 15:13

3 Answers3

6

Non-heap-allocated arrays of char have no specific requirements on their alignment. So your buffer of a thousand characters could be on an odd offset. Trying to read an int from that offset (reinterpreted as an int pointer obvious) would either result in poor performance or even a bus error on some hardware if the compiler doesn't split it up into separate read+bitmask operations.

Heap-allocated arrays of char are guaranteed to be aligned suitably to store any object type, so this is always an option.

For non-heap based storage, use boost::aligned_storage which ensures that the space is aligned properly for general use.

Mark B
  • 95,107
  • 10
  • 109
  • 188
3

You can find an overview on wikipedia. More in depth on the IBM site: Data alignment: Straighten up and fly right

0

Imagine the case where addresses must be 16-byte aligned like for example the PS3. And then imagine that the shift == 1. This would then for sure be a non 16-byte aligned pointer which would not work on this machine.

Roel Van Nyen
  • 1,279
  • 1
  • 9
  • 19