GCC不合理优化消除未使用变量,是否为bug?如何禁止该优化?
是否属于GCC bug
这不属于GCC的bug,是符合C标准的合法优化行为。
C语言标准明确规定:编译器有权消除所有不会产生可观测副作用的代码。问题的核心原因是:
- 定义
NDEBUG后,assert()会被展开为空语句,handle、handle2两个变量没有被后续代码使用,属于无意义的赋值目标 - 你用到的
STREAM_TO_UINT16宏把「给变量赋值」和「修改局部指针变量stream的值」两个操作绑定在一起,编译器判定整个宏展开后的代码块没有可观测的对外影响,因此整体消除,这是完全符合优化规则的正常行为,不属于编译器缺陷。
无需修改Bluedroid源码的解决方案
可根据你的实际场景选择以下任意一种方案:
- 最优方案:重定义assert宏保留表达式计算
编译出问题的Bluedroid源文件时,添加编译参数-D 'assert(expr)=((void)(expr))',该定义会覆盖标准assert.h的NDEBUG分支逻辑,仅关闭断言失败的终止逻辑,仍然会计算assert括号内的表达式值。这样handle、handle2会被判定为已使用,宏内的stream自增逻辑会被完整保留,且几乎没有额外运行时开销。 - 关闭对应文件的死代码消除优化
若不方便修改宏定义,可以给问题源文件单独添加编译参数-fno-tree-dce,关闭GCC的死代码消除优化,这类代码块就不会被删除,仅会小幅降低该文件的优化效率,对整体性能影响极小。 - 降低对应文件的优化等级
也可以给问题源文件单独指定-O1优化等级,该等级下不会消除这类绑定了指针操作的未使用变量赋值逻辑。
内容的提问来源于stack exchange,提问作者philippe_44
相关产品推荐
相关产品推荐

