为何GCC(10.1+)与Clang会优化掉该循环?合规性疑问
GCC/Clang为何会优化掉看似正确的
while(flag)循环? 代码示例
C++源码
extern int flag; extern "C" void wait() { while(flag); } int flag = 4;
GCC/Clang生成的汇编代码
wait: ret flag: .long 4
优化行为的原因
这种看似错误的优化是完全符合C++标准的,核心原因有两点:
- 无副作用的无限循环属于未定义行为:C++标准规定,没有任何可见副作用的无限循环(既不修改可访问对象,也不执行输入输出操作)属于未定义行为。编译器可以对未定义行为做任意处理,包括直接移除循环,让函数直接返回。在这段代码中,如果
flag始终为4,while(flag);就是一个无限循环且没有任何副作用,触发了未定义行为,因此编译器有权优化掉它。 - 普通变量的跨线程修改无同步时,编译器可忽略:即使考虑多线程场景,
flag是普通int类型,既没有用volatile修饰,也没有使用std::atomic或同步原语(如互斥锁)。根据C++内存模型,编译器可以假设当前线程没有修改flag的情况下,其他线程对flag的修改对当前线程不可见。因此编译器会将flag视为不会变化的值(初始为4),判定循环条件永远为真,进而触发上述的未定义行为优化。
如果要让编译器保留循环并正确感知跨线程的flag修改,需要将flag声明为volatile int,或者使用std::atomic<int>来保证内存可见性。
内容的提问来源于stack exchange,提问作者MemoryWrangler
相关产品推荐
相关产品推荐

