C++ 应用程序在 Visual Studio 2022 (>= 17.10) 上的 std::minmax_element 上崩溃

问题描述 投票:0回答:1

最新版本的 Visual Studio C++ 编译器破坏了我们的代码。我们的应用程序使用 STL 算法,如测量样本上的 std::minmax_element。有时,设备不会提供有效的样本,而是会插入 NaN 元素。

到目前为止,STL 算法完全忽略了 NaN(GCC、CLANG、Visual Studio)

使用这个最小示例可以重现崩溃:

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

int main()
{
    const double inf = std::numeric_limits<double>::infinity();
    const double nan = std::numeric_limits<double>::quiet_NaN();
    double values[] = {0, -inf, nan};
    const auto mm = std::minmax_element(std::begin(values), std::end(values));
    std::cout << "Min: " << *mm.first << std::endl;
    std::cout << "Max: " << *mm.second << std::endl;
    return std::distance(mm.first, mm.second);
}

游乐场:https://gcc.godbolt.org/z/GhTPsfj5q

预期:

example.cpp
ASM generation compiler returned: 0
example.cpp
Execution build compiler returned: 0
Program returned: 1
Min: -inf
Max: nan

VS 2022 >= 17.10

example.cpp
ASM generation compiler returned: 0
example.cpp
Execution build compiler returned: 0
Program returned: 4294967295
Min: -inf
Max: 0

MS 的 STL 专家认为 STL 算法需要“严格弱排序”。包含 NaN 的序列不满足此要求,因此我们在未定义行为的世界中徘徊。

我团队的一位 STL 专家了解该标准,因此只有在 C++-20 中使用 std::less 时才需要严格弱排序。

我仍然需要知道,在将来调用 STL 算法进行保存之前,我们是否必须预先清理数据序列。

谢谢你1000遍!

再见冈瑟

c++ c++17
1个回答
0
投票

来自 C++17 最终草案

28.7 排序及相关操作

  1. 28.7 中的所有操作都有两个版本:一种采用 Compare 类型的函数对象,另一种使用
    operator<
  2. Compare 是一个函数对象类型(23.14)。应用于 Compare 类型的对象的函数调用操作的返回值,当根据上下文转换为
    bool
    (第 7 条)时,如果调用的第一个参数小于第二个参数,则产生
    true
    ,否则产生
    false
    Compare comp
    用于假设排序关系的算法。假设 comp 不会通过解引用迭代器应用任何非常量函数。
  3. 对于所有采用
    Compare
    的算法,有一个版本使用
    operator<
    代替。也就是说,
    comp(*i, *j) != false
    默认为
    *i < *j != false
    对于 28.7.3 中描述的算法以外的算法,
    comp
    应对值产生严格的弱排序。

28.7.3 列出了许多二分搜索算法(

lower_bound
upper_bound
equal_range
binary_search
),而
minmax_element
不在其中,因此它不能免除严格的弱排序要求,这意味着包括该范围内的
NaN
会使您的程序具有未定义的行为。

© www.soinside.com 2019 - 2024. All rights reserved.