简体   繁体   English

这个来自 gcc 的越界警告是错误的吗?

[英]Is this out-of-bounds warning from gcc erroneous?

Earlier today, gcc gave me a warning that I belive to be erroneous and now I am very unsure if it is an actual compiler bug(usually highly unlikely) or a bug in my code(usually highly likely).今天早些时候,gcc 给了我一个警告,我认为这是错误的,现在我非常不确定这是一个实际的编译器错误(通常极不可能)还是我的代码中的错误(通常极有可能)。 I managed to reduce it down to the following code:我设法将其简化为以下代码:

#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这是编译器资源管理器

When compiled with optimization level -O2 or higher with gcc 12.1 or trunk, this warning about an out-of-bounds access is emitted:当使用 gcc 12.1 或主干使用优化级别 -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{};

I believe that to be mistaken.我相信这是错误的。 According to my limited understanding, valid is only incremented once and will always be 1.根据我有限的理解,valid 只会增加一次,并且永远是 1。

Even if the condition were replaced with some unpredictable function call, in the worst case it would be true every time, yielding valid==8 at the end of the loop, which should still be alright?即使条件被一些不可预测的 function 调用替换,在最坏的情况下,每次都为真,在循环结束时产生 valid==8,这应该还可以吗?

Additionally, I have thus far made the following observations:此外,到目前为止,我提出了以下意见:

  • The warning is not produced at lower optimization levels, on gcc <=11 or on clang.在较低的优化级别、gcc <=11 或 clang 上不会产生警告。
  • Interestingly, the warning is also not produce with array sizes >8 or <6, only for sizes 6,7, and 8.有趣的是,警告也不会在数组大小 >8 或 <6 时产生,仅适用于大小 6,7 和 8。
  • When I remove the condition inside the loop body(the "if(i==0)", to increment every time and always yield valid==8), the warning disappears.当我删除循环体内的条件(“if(i==0)”,每次递增并始终产生有效==8)时,警告消失。
  • When I add the condition before the sort call(and thereby provide the compiler with an additional hint about the limits of valid), the warning disappears.当我在排序调用之前添加条件时(从而为编译器提供有关有效限制的附加提示),警告消失。

Especially the latter two make me believe I might have managed to confuse gcc's analysis somehow, but also make me question if I am overlooking something obvious or managed to introduce some subtle undefined behaviour in my code.尤其是后两者让我相信我可能设法以某种方式混淆了 gcc 的分析,但也让我质疑我是否忽略了一些明显的东西或设法在我的代码中引入了一些微妙的未定义行为。

Am I misunderstanding something in my sleep deprived state or did I encounter a genuine, mostly harmless, compiler bug?我是在睡眠中误解了一些东西,剥夺了 state 还是我遇到了真正的、几乎无害的编译器错误?

It is indeed a compiler bug, as can be seen in this bugzilla report , which contains almost identical code to the one in my question.这确实是一个编译器错误,可以在这个 bugzilla 报告中看到,其中包含与我的问题中的代码几乎相同的代码。

Thanks to Marc Glisse for providing this link to a lot of similar bugs and thereby helping me track down the relevant one.感谢 Marc Glisse 提供了许多类似错误的链接,从而帮助我找到了相关错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM