📜 ⬆️ ⬇️

About alignment of memory on ARM processors on a simple example

Suppose we have a function that takes a pointer. We know that the pointer contains a zero-terminal string, followed by a 4-byte integer. The task is to output a string and an integer to the console. You can solve it like this:

void foo(void* data_ptr) { //       char* str = (char*)data_ptr; //            int* value = (int*)(str+strlen(str)+1); //    printf("%s %d", str, *value); } 

Quite a trivial task, isn't it? Check on the computer (x86), everything is OK. We load on a board with ARM. And, not having time to shoot himself in the foot, stepping on a rake. Depending on the content of the string, the integer value is output either normal or crooked. We check pointers, check the memory to which they point. Everything is okay.

Note that the integer is displayed exactly when the length of the string is 3, 7, 11, ..., 4 * n-1. Yeah. We take a closer look at the memory and on the output in “crooked” cases. For example, if the memory looks like this:

Address:
')
 |0x00|0x01|0x02|0x03|0x04|0x05|0x06|0x07|0x08| 

Data:

 |0x31|0x31|0x31|0x31|0x00|0x01|0x00|0x00|0x00| 

At the output we get the string "1111" and the integer 0x00000100 instead of 0x00000001.

Conclusion: Despite the fact that the expression * value we refer to the pointer 0x05, the data is returned to us as if the conversion occurs on the pointer 0x04 (or another multiple of 4).

So how to solve this problem correctly? That's how:

 void foo(void* data_ptr) { int value; //    char* str = (char*)data_ptr; memcpy(&value, str+strlen(str)+1, sizeof(int)); //    printf("%s %d", str, value); //  } 

In this case, everything is always in place.
Thanks for attention!

UPD: Corrected an obvious error.

Source: https://habr.com/ru/post/309144/


All Articles