C++循环前进进度判定:栅栏是否属于原子/同步操作?
C++循环的前进进度要求与栅栏操作的未定义行为争议
标准对前进进度的要求
(6.9.2.3p1) 实现可假定任意线程最终会执行以下操作之一:
- 终止;
- 调用
std::this_thread::yield函数;- 调用库I/O函数;
- 通过volatile左值执行访问;
- 执行同步操作或原子操作;
- 继续执行平凡无限循环([stmt.iter.general])。[C++23新增]
不符合上述任何操作且不属于“平凡无限循环”的无限循环,会导致未定义行为(UB)。
核心问题
针对上述第5点,栅栏(fence)是否属于“同步操作或原子操作”?如果存在一个非平凡无限循环,循环体仅包含atomic_signal_fence()或atomic_thread_fence()且无其他副作用,这类代码是否会触发未定义行为?
目前C++标准并未明确定义或列出“原子操作”的详尽范围:
- 《atomics.fences》章节将栅栏描述为“同步原语”,且栅栏本身没有可观测的实际效果,似乎不应被算作可观测效果;
- 但《atomics.order》p4提到“所有
memory_order::seq_cst操作(包括栅栏)”的全序,这又暗示栅栏被视为一种“操作”。
附加问题
如果栅栏使用明确标注为无效果的memory_order_relaxed内存顺序,是否会改变结论?
编译器表现差异
测试代码
bool b = true; while (b) { std::atomic_signal_fence(std::memory_order_relaxed); }
- Clang:会直接删除整个循环,甚至不会生成该函数的任何代码——这是编译器处理无条件UB函数的典型行为;
- GCC:会生成无限空循环,尽管它会删除不含栅栏的同类循环。对于
atomic_thread_fence,GCC会生成带屏障指令的无限循环,其他内存顺序下也存在类似差异。
内容的提问来源于stack exchange,提问作者Nate Eldredge
相关产品推荐
相关产品推荐

