0

I've written a small program that resembles the problem I'm facing in my project. The question is, why does it crash when run on HP-UX platform ?

Error :

si_code: 1 - BUS_ADRALN - Invalid address alignment

Code :

int main()
{
    uint8_t *cmd ;
    cmd = (uint8_t *) malloc(77);
    uint32_t gen = 20; 
    *(uint32_t*)&cmd[10] = gen;  /* crash here */
    return 0;
}
Manoj Hirway
  • 131
  • 1
  • 7
  • possible duplicate of [what does "BUS\_ADRALN - Invalid address alignment" error means?](http://stackoverflow.com/questions/3246441/what-does-bus-adraln-invalid-address-alignment-error-means) – David Kiger Feb 17 '15 at 05:59
  • *(uint32_t*)&cmd[11] = gen; /* crash here */ --> Can you try "11" instead of "10"? – simurg Feb 17 '15 at 06:15
  • It crashes the same way for 11. – Manoj Hirway Feb 17 '15 at 06:22
  • @ManojHirway How about 12? – Arkku Feb 17 '15 at 06:26
  • In order for `cmd[10]` to be aligned to 32 bits, `cmd` has to be aligned to 16 bits **and not** aligned to 32 bits. If this is not the case, **AND** your platform (i.e., underlying HW architecture + designated compiler) does not support unaligned load/store operations, then this operation will yield undefined behavior. If you're lucky, then it will immediately crash and "let you know" that there is something wrong in this line. If you're unlucky, then it will just store a value into a different offset within `cmd`, and the program will behave unexpectedly. – barak manos Feb 17 '15 at 06:47
  • @barakmanos By specifications of `malloc`, `cmd` will never be “not aligned to 32 bits” on a platform that has a data type requiring such alignment – `malloc`ed memory is aligned for any data type, so in this case the incorrect alignment is basically guaranteed. – Arkku Feb 17 '15 at 06:53
  • BTW, this also violates strict aliasing, not only alignment requirements. `memcpy(&cmd[10], &gen, sizeof gen);` should solve both issues. – mafso Feb 17 '15 at 09:49

1 Answers1

3

&cmd[10] is not aligned properly for storing a 32-bit integer – as each element of cmd is one byte long and the address returned by malloc is correctly aligned for “any type”, the 11th element of cmd won't be at an address divisible by 4.

Arkku
  • 41,011
  • 10
  • 62
  • 84
  • Thanks. But, we aren't we referring to a 4-bytes together when we are typecasting it as (uint32_t *)&cmd[10] ? – Manoj Hirway Feb 17 '15 at 06:51
  • @ManojHirway By casting you are treating the data as a `uint32_t`, and the compiler generates code that works on that type, not code that works on “any 4 bytes together”… So the alignment requirements of `uint32_t` come to play. (The clang compiler actually produces a warning about this line in your code if you have `-Wcast-align` enabled.) – Arkku Feb 17 '15 at 06:56