GCC与ARM编译器v6下section属性标记变量的段内排布顺序规则
同自定义段内变量排布规则说明
核心结论
不管是GCC还是ARM Compiler v6,都没有官方保证跨翻译单元的同段变量的相对排布顺序,绝对不能依赖默认排序实现跨CPU地址共享,Keil官方推荐的结构体方案是唯一稳定可控的实现方式。
GCC 排布规则
- 同一翻译单元(同个.c/.cpp文件)内部的同段变量:按代码中声明的先后顺序排布,在满足变量对齐要求的前提下地址递增,这个行为是GCC明确保证的。
- 跨翻译单元(比如示例中file1.cpp的a1和file2.cpp的a2):相对顺序完全由链接时输入的目标文件顺序决定,先传入链接器的.o文件里的变量会排在段的更前面,没有固定的默认规则,GCC官方明确将跨文件同段变量的相对地址归类为未定义行为,不受兼容性保证。
ARM Compiler v6(armclang)排布规则
- 同一翻译单元内部的同段变量:和GCC行为一致,按声明顺序排布。
- 跨翻译单元的同段变量:同样没有官方固定排序规则,默认相对顺序由链接时目标文件的输入顺序决定,ARM官方文档明确说明不会保证跨翻译单元的同段变量的相对地址稳定性,调整编译选项、升级编译器版本都有可能改变排布顺序。
当前用法的风险
你现在的跨文件同段变量用法,地址顺序完全不可控:只要调整编译链接顺序、开不同等级的优化、更换编译器版本,都有可能改变a1和a2的相对地址,对于需要和其他CPU共享内存的高可靠性场景来说,会出现随机、难以定位的通信错误,完全不符合要求。
稳定实现方案
唯一符合官方规范的可控地址排布方案如下:
- 将所有需要固定相对地址的共享变量统一定义到同一个结构体中,C标准严格保证结构体内部成员按声明顺序排布,地址偏移固定。
- 仅在单个翻译单元中定义该结构体的实例,将整个结构体放到你指定的自定义段中。
示例代码:
// 自定义段宏定义 #define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__))) // 公共头文件中定义共享内存结构体,所有访问该内存的CPU都要复用这个定义保证对齐和顺序一致 typedef struct { int a1; int a2; // 其他共享变量按需求顺序添加 } SharedDevMem; // 仅在单个.c文件中定义实例,放入指定段 PLACE_IN_SECTION("A") static SharedDevMem g_shared_dev_mem;
内容的提问来源于stack exchange,提问作者schanti schul
相关产品推荐
相关产品推荐

