对齐与非对齐访问
什么是非对齐访问
在机器指令层面,当尝试从不能被 N 整除 (addr % N != 0) 的起始地址读取 N 字节的数据时即发生了非对齐内存访问。举例而言,从地址 0x10004 读取 4 字节是可以的,然而从地址 0x10005 读取 4 字节数据将会是一个非对齐内存访问。这里 N 就是数据的自然对齐值
编译器非对齐访问支持
- 使能非对齐访问
-munligned-access
- 禁止非对齐访问
-mno-unligned-access
对于 ARM
架构,默认情况下 pre-ARMv6
,ARMv6-M
及以 ARMv8-M
为基线架构的系列不支持非对齐访问,其他所有系列默认都是支持非对齐访问的。
对于 x86
架构,不支持 -mno-unligned-access
和 -munligned-access
编译选项,非对对齐访问暂未研究
对于 RISC-V
架构,暂未研究
GCC 文档对于该编译选项的原文描述
Enables (or disables) reading and writing of 16- and 32- bit values from addresses that are not 16- or 32- bit aligned. By default unaligned access is disabled for all pre-ARMv6, all ARMv6-M and for ARMv8-M Baseline architectures, and enabled for all other architectures. If unaligned access is not enabled then words in packed data structures are accessed a byte at a time. The ARM attribute Tag_CPU_unaligned_access is set in the generated object file to either true or false, depending upon the setting of this option. If unaligned access is enabled then the preprocessor symbol __ARM_FEATURE_UNALIGNED is also defined
会产生非对齐访问的场景
指针强转
C 语言中类型强转的支持导致可能出现非对齐的访问出现。例如:
#include <stdio.h>
int main(int argc, char argv[])
{
printf("tyustli\r\n");
char test_buf1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10};
printf("%p\r\n", &test_buf1[0]); // 0x7ffe63b95aae
printf("%p\r\n", &test_buf1[1]); // 0x7ffe63b95aaf
printf("%p\r\n", &test_buf1[2]); // 0x7ffe63b95ab0
printf("%p\r\n", &test_buf1[3]); // 0x7ffe63b95ab1
int value = *(int *)&test_buf1[3]; // 此时按照 int 去访问 0x7ffe63b95ab1 地址,就是非对齐的
printf("0x%x\r\n", value);
return 0;
}
指针的强制类型转换要小心,短类型的数据到长类型的转换要特别注意。
结构体成员
如果代码中使用了 __attribute__((packed))
定义的结构体,会出现结构体成员是非对齐的,此时如果没有使能非对齐访问会触发 abort
异常
struct test_struct_pack {
short test_value1;
int test_value2;
char test_value3;
} __attribute__((packed));
int main()
{
struct test_struct_pack test_pack;
int val = test_pack.test_value2;
return val;
}
参考链接
- https://blog.csdn.net/FJDJFKDJFKDJFKD/article/details/108730380
- http://www.360doc.com/content/22/0730/20/38701044_1041998980.shtml
- https://club.rt-thread.org/ask/article/e179941c3f5c1955.html