跨编译单元下volatile与编译器优化的安全性确认
嵌入式裸机C++中volatile用法的两个关键问题确认
示例代码
// main.cpp bool flag = false; // note: not volatile void some_interrupt_routine() { // hw: no nested interrupts possible flag = true; } void main() { while (true) { // assume atomic reads/writes of "flag" if (flag == true) { flag = false; // do something(调用其他编译单元的函数) } } }
前提假设
- 使用启用优化的类GCC编译器
- 遵循C++14标准
- 独立编译各cpp文件后链接,未启用链接时优化(LTO)
- 无硬件同步指令、编译器同步内联函数
- 编译器未实现
std::atomic - flag的读写为原子操作
问题1:能否安全假设,因编译器无法确定"do something"调用的其他编译单元函数是否会修改flag,故不会优化该循环?
可以安全假设。在独立编译(无LTO)的场景下,编译main.cpp时,编译器无法获知其他编译单元的函数逻辑,必须考虑外部函数可能修改全局变量flag的情况。按照C++14标准,编译器不能对跨编译单元可见的全局变量做出“不会被外部修改”的假设,因此不会将循环优化为无操作死循环——每次循环都会重新从内存读取flag的值,而非将其缓存到寄存器后不再更新。
问题2:能否安全假设,中断函数some_interrupt_routine的汇编代码会始终对全局变量flag执行写操作?(编译器无法知晓其他编译单元是否会调用该函数并检查flag值,仅链接器可能移除该函数)
可以安全假设。编译该中断函数所在的编译单元时,编译器无法确定该函数是否会被硬件触发或被其他编译单元的代码间接引用,因此会完整生成对flag执行写操作的汇编代码。只有链接器在确认该函数未被任何代码或硬件中断向量表关联的情况下,才可能将其从最终可执行文件中移除,但函数内部的写flag逻辑在编译阶段一定会被正确生成。
内容的提问来源于stack exchange,提问作者IAmPropper
相关产品推荐
相关产品推荐

