c++ - gcc 发出的这个越界警告是错误的吗?

标签 c++ gcc gcc-warning

今天早些时候,gcc 给了我一个警告,我认为这是错误的,现在我非常不确定它是一个真正的编译器错误(通常不太可能)还是我代码中的错误(通常很可能)。我设法将其简化为以下代码:

#include <algorithm>
#include <array>
#include <iostream>

int main()
{
    std::array<int,8> test{};
    int valid = 0;
    for(int i=0;i<8;++i)
    {
        if(i==0)
            test[valid++] = 0;
    }
    
//    if(valid<8)
        std::sort(test.begin(),test.begin()+valid);
}

Here it is on Compiler explorer

当使用 gcc 12.1 或 trunk 使用优化级别 -O2 或更高级别编译时,会发出有关越界访问的警告:

In file included from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/algorithm:61,
                 from <source>:1:
In function 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]',
    inlined from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/stl_algo.h:1844:5,
    inlined from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/stl_algo.h:1940:31,
    inlined from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' at /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/stl_algo.h:1932:5,
    inlined from 'void std::sort(_RAIter, _RAIter) [with _RAIter = int*]' at /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/stl_algo.h:4820:18,
    inlined from 'int main()' at <source>:16:15:
/opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/stl_algo.h:1849:32: error: array subscript 16 is outside array bounds of 'std::array<int, 8> [1]' [-Werror=array-bounds]
 1849 |           std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
      |           ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>: In function 'int main()':
<source>:7:27: note: at offset 64 into object 'test' of size 32
    7 |         std::array<int,8> test{};

我相信这是错误的。据我有限的理解,valid只增加一次,永远是1。

即使条件被替换为一些不可预测的函数调用,在最坏的情况下它每次都为真,在循环结束时产生 valid==8,这应该仍然可以吗?

此外,到目前为止,我还做出了以下观察:

  • 警告不会在较低的优化级别、gcc <=11 或 clang 上产生。
  • 有趣的是,警告也不会在数组大小 >8 或 <6 时产生,仅适用于大小 6、7 和 8。
  • 当我删除循环体内的条件(“if(i==0)”,每次递增并始终产生 valid==8)时,警告消失。
  • 当我在排序调用之前添加条件(从而为编译器提供有关 valid 限制的额外提示)时,警告消失。

尤其是后两者让我相信我可能设法以某种方式混淆了 gcc 的分析,但也让我怀疑我是否忽略了一些明显的东西或设法在我的代码中引入了一些微妙的未定义行为。

我是在 sleep 不足的状态下误解了什么,还是遇到了真正的、几乎无害的编译器错误?

最佳答案

这确实是一个编译器错误,如 in this bugzilla report 所示,它包含与我问题中的代码几乎相同的代码。

感谢 Marc Glisse 提供 this link to a lot of similar bugs 并帮助我找到相关的。

关于c++ - gcc 发出的这个越界警告是错误的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73423060/

相关文章:

c++ - : "C/C++ Indexer" 期间发生内部错误

c++ - C++ 中作为右值的常量(11)

c++ - 抑制 GCC 警告

c++ - 递归目录和文件流以及搜索字符串

c++ - 声明一个具有 C 调用约定但具有内部链接的 C++ 函数

c++ - (C++) 堆上的内存变得可访问/被删除

c - 函数以某种方式从一次调用中返回两次

gcc - 与 Intel 语法相比,AT&T 语法中源操作数的顺序是什么?

c++ - 为什么将除法改为右移时会发生有符号溢出?

c - 在 C 程序中,收到警告 : "Statement with no effect"