std::sort 调用导致下标超出范围编译时错误

std::sort invocation causes subscript out of range compile-time error

提问人:mmodel1 提问时间:7/22/2023 最后编辑:Konrad Rudolphmmodel1 更新时间:8/28/2023 访问量:231

问:

以下代码编译失败,并出现错误:“数组下标 16 超出 ...的数组边界”。 我不明白为什么,保证是 <= arr1.size()。w

https://godbolt.org/z/5n5KohsnW

#include <array>
#include <algorithm>
#include <tuple>

extern bool test_func();

int tempfunc() 
{
    std::array<std::tuple<double,int>,5> arr1;
    int w = 0;
    for (int i = 0; i < 5; ++i ) {
        if( test_func()) {
            arr1[w] = {3.,4};
            w++;
        }
    }
    std::sort(arr1.begin(), arr1.begin() + w);

    return 0;
}
C++ 数组 排序

评论

2赞 Tim Randall 7/22/2023
循环终止后的值是多少?wfor
1赞 HolyBlackCat 7/22/2023
@TimRandall 5 或更少,如问题中所述。还是我错过了一些明显的东西?
1赞 Drew Dormann 7/22/2023
乍一看,这似乎是 gcc 12 中引入的回归。的运行时值不应在编译时触发错误。w
3赞 Sam Varshavchik 7/22/2023
显示的代码没有问题。另一个 gcc 优化 frankenbug。加入派对...Bug 100366,Bug 108165,还有什么?
1赞 sweenish 7/22/2023
对可能包含未初始化值的范围进行排序“没有”问题。

答:

-1赞 Cornel 8/28/2023 #1

该错误可能是由不同编译器上的不同行为引起的。也与 w 变量相关,因为函数 bool test_func();可以返回 false 作为循环中的 if 条件,这意味着每次完成时都不能保证 w 的值为 5(根据函数返回的值可以更小)。

您可以通过在排序行中将 w 更改为 5 来解决它,或者更好的是 arr1.size() 也可以,因为它的大小为最初声明的 5。

std::sort(arr1.begin(), arr1.begin() + 5);

或者用这个代替它:

std::sort(std::begin(arr1), std::end(arr1));

此外,要打印每个元组的值,请在循环中尝试以下操作:

std::cout << "First is: " << std::get<0>(arr1[i]) << " and Second is " << std::get<1>(arr1[i]) << std::endl;

评论

0赞 HolyBlackCat 8/28/2023
它返回 false 如何解释错误?
0赞 Cornel 8/28/2023
我编辑了我的答案。再检查一次。它与变量 w 相关。我已经在我的编译器以及给定的在线编译器链接中对此进行了测试。
0赞 HolyBlackCat 8/28/2023
我看不出此更改与 OP 的错误有何关系。他们的代码应按原样工作。
0赞 Cornel 8/28/2023
分配给元组数组的排序函数的偏移量超过数组的实际大小。它正在尝试对数组元素进行排序,以查找数组实际容纳的大小(5 个元素)以外的大小。
0赞 HolyBlackCat 8/28/2023
w永远不能比 OP 的代码更大。5
-1赞 Cornel 8/28/2023 #2

如果最新的 GCC 仍然存在问题,建议在键/值对为 <double、int>的元组数组上使用类似 map(无序映射并在末尾对其进行排序或简单的有序映射)之类的东西。