编译器警告——GCC优化影响边界检查



考虑以下示例:

int a[4];
int main() {
  a[4] = 12; // <--
  return 0;
}

这显然是一个越界错误,不是吗?我想知道gcc何时会对此发出警告,并发现只有在优化为-O2或更高时才会这样做(这受-ftree-vrp选项的影响,该选项仅为-O2或更高自动设置)。我真的不明白为什么这是有意义的,以及gcc不发出警告是否正确。

文档是这样说的:

这允许优化器删除不必要的范围检查,如数组绑定检查和空指针检查。

不过,我还是不明白为什么那个检查是不必要的?

您的示例是常量传播的情况,而不是值范围传播,它肯定会在我的gcc(4.5.1)版本上触发警告,无论-ftree-vrp是否启用。

一般来说,Java和Fortran是gcc支持的唯一的语言(默认是Java,如果你通过-fbounds-check显式地要求Fortan)将生成检查数组边界的代码。

然而,尽管C/c++不支持任何这样的事情,编译器仍然会在编译时警告你,如果它认为有什么不对劲。对于常量,这是很明显的,对于变量范围,这有点困难。

子句"允许编译器删除不必要的范围检查"涉及以下情况:例如,您使用无符号8位宽变量来索引>256个条目的数组,或使用无符号16位值来索引>65536个元素的数组。或者,如果你在循环中迭代数组,并且(变量)循环计数器由可以被证明为编译时常量的值(合法数组索引)限定,那么计数器永远不可能超出数组边界。
在这种情况下,编译器既不会警告您,也不会为支持此功能的目标语言生成任何代码。

最新更新