You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC-O2优化致无副作用循环变无限循环的合法性疑问

GCC -O2优化引发无限循环的未定义行为分析

使用GCC 8.4.3并添加-O2编译选项构建程序时,以下循环被编译为无限循环的汇编代码:

for(int i=0; i < PCU_MAX; i++) 
{
     auto loc = getApp()->Loc[i + 1 + PCU_LOCATION];
     if (loc.isUpdated() ) loc.setUpdated ( false );
}

最初程序挂起时误以为是死锁,未检查汇编代码;最终在GDB中尝试打印变量i时,发现该变量已被优化掉。对应的汇编代码如下:

0x782f20 <MainWindow::updateInfo(int)+352> mov 0xc31899(%rip),%rsi
0x782f27 <MainWindow::updateInfo(int)+359> mov $0x882700,%edi
0x782f2c <MainWindow::updateInfo(int)+364> callq 0x42da40 <_ZNK11QMetaObject4castEP7QObject@plt>
0x782f31 <MainWindow::updateInfo(int)+369> jmp 0x782f20 <MainWindow::updateInfo(int)+352>

已知的两个核心错误

  • getApp()->Loc是数组,代码中使用auto loc =会进行值拷贝,正确写法应为auto& loc =;
  • 循环无可见副作用,GCC优化掉变量i后,循环终止条件消失,进而形成无限循环。

核心疑问

  1. 这种优化是否属于合法的未定义行为(UB)?
  2. 循环存在数组越界问题——最后一次迭代会访问数组末尾的下一个元素,虽该区域为同类型“安全区域”,但访问数组末尾后一个元素是否属于UB?

相关论点

  • 论点1:获取数组末尾后一个元素的地址不属于UB,但访问或修改该元素属于UB;
  • 论点2:isUpdated()和setUpdated()虽看似与Loc元素相关,但实际无对应副作用;不过调用非静态成员函数时,即使this指针指向正确对象,是否仍属于UB?

补充现象

移除上述两个错误因素中的任意一个,循环均可正常运行;但仅移除if (loc.isUpdated() ) loc.setUpdated ( false );并改为auto& loc时,仍会出现无限循环。这似乎是GCC先优化掉i,再以“无限循环无可见副作用”为由判定为UB。

内容的提问来源于stack exchange,提问作者Swift - Friday Pie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:52:43