C++11下如何实现自定义内存段中结构体的编译期静态初始化
问题根因
你所使用的C++11标准未强制要求非聚合类型的constexpr全局变量必须完成编译期常量初始化,面向嵌入式场景的Xtensa架构GCC工具链默认会将带自定义构造函数的全局对象加入静态初始化列表,在main函数执行前运行构造逻辑完成赋值,也就是你观察到的运行时初始化汇编代码。
可行解决方案(均适配C++11标准)
方案1:改用聚合类型+聚合初始化(最推荐)
移除结构体的自定义构造函数,将其改为聚合类型,直接对全局const变量做聚合初始化,工具链会直接将初始化值写入对应自定义段,无任何运行时开销:
struct ParamBuff { int32_t first_val; int32_t second_val; }; __attribute__((section(".my_section.rodata"))) const ParamBuff param_buff = {0xcafecafe, 0xdeadbeaf};
如果需要保留构造的便利性,可以额外加一个静态constexpr构造方法:
struct ParamBuff { int32_t first_val; int32_t second_val; static constexpr ParamBuff make() { return {0xcafecafe, 0xdeadbeaf}; } }; __attribute__((section(".my_section.rodata"))) const ParamBuff param_buff = ParamBuff::make();
方案2:保留自定义构造函数,补充属性修饰
如果一定要保留自定义constexpr构造函数,可以给变量额外加used、visibility("hidden")属性,强制工具链做编译期初始化:
struct ParamBuff { int32_t first_val; int32_t second_val; constexpr ParamBuff() : first_val(0xcafecafe),second_val(0xdeadbeaf){}; }; __attribute__((section(".my_section.rodata"), used, visibility("hidden"))) constexpr ParamBuff param_buff {};
同时需要检查链接脚本中自定义段的属性配置,确保段标记为可分配、可加载,示例配置参考:
.my_section.rodata : ALIGN(4) { *(.my_section.rodata*) } > dram0_0 AT> dram0_0
方案3:C风格常量数组兜底
如果前两种方案未生效,可以用最稳妥的常量数组方式声明,使用时做类型转换即可:
__attribute__((section(".my_section.rodata"))) const int32_t param_buff_raw[2] = {0xcafecafe, 0xdeadbeaf}; // 业务代码使用时转换 const ParamBuff* param_buff = reinterpret_cast<const ParamBuff*>(param_buff_raw); some_variable = param_buff->first_val;
内容的提问来源于stack exchange,提问作者user1651647
相关产品推荐
相关产品推荐

