具有不可预测循环行为的 C 编译谜题
以下代码提出了一个有趣的编译问题:
相反当预期输出“0, 1, 2, 3”终止时,代码会产生“0, 1, 2, 3, 4, 5, ...”的无限重复。经调查,比较 di < 1。 4 无法正常工作,导致无限循环。
禁用看似无害的赋值 delta = mc[di] 神奇地修复了问题,生成预期的输出。这个简单的操作会导致什么问题?
深入研究未定义的行为
解开这个谜团的关键在于理解未定义的行为。赋值 delta = mc[di] 会在循环的最后一次迭代中触发对数组的越界访问。虽然许多编译器可能根据优化策略假设没有未定义的行为,但这种假设本质上是有缺陷的。
打开优化的 GCC 可以在假设不存在未定义行为的情况下积极优化循环。这种优化导致错误的推断:di
因此,循环变成无限循环,因为条件 di
揭开编译器的内部工作原理
仔细检查优化后的代码表明 di
与此行为相反,带有 -fsanitize=undefined 的 Clang 会捕获这种情况。然而,具有相同标志的 GCC 在此特定实例中无法发出警告。
未定义行为的危险
未定义行为,由 C 标准定义,允许出现不可预测的结果,包括完全无视情况。应不惜一切代价避免未定义的行为,因为它可能导致编译器不一致和意外的运行时行为。
为了避免此类陷阱,程序员应该努力编写符合预期语义的定义良好的代码。编译器还应该实施适当的防御措施,以提醒开发人员潜在的未定义行为。
以上是为什么为复杂变量赋值会导致 C 程序中的无限循环,即使它看起来是一个看似无害的操作?的详细内容。更多信息请关注PHP中文网其他相关文章!