The newest version of Visual Studio C++ compiler broke our code. Our application uses STL algorithm like std::minmax_element on measured samples. Sometimes the devices do not deliver a valid sample and a NaN element is inserted instead.
Up to now the STL algorithms ignored NaN completely (GCC, CLANG, Visual Studio).
The crash is reproducible with this minimum example:
#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);
}
Playground: https://gcc.godbolt.org/z/GhTPsfj5q
Expected:
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
The STL expert from MS arguments that STL algorithms expect "strictly-weak-ordering". A sequence containing NaN does not fulfill this requirement and therefore we wander the world of undefined behavior.
A STL expert from my team understands the standard so that strictly-weak-ordering is only needed in C++-20 when using std::less.
Still, I need to know, if we have to cleanup our data sequences upfront, before calling STL algorithms in future to be safe.
A STL expert from my team understands the standard so that strictly-weak-ordering is only needed in C++-20 when using std::less.
They understand wrong. The change between C++17 and C++20 was changing the default comparison from < to std::less. It has always been a requirement for whichever comparison is used to be a strict-weak-order.
This change only affects algorithms applied to ranges of pointers, as std::less is defined to use < for everything apart from pointers, where it synthesizes a strict-weak-order. For historical reasons, it is undefined to apply < to pointers to elements of distinct arrays.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With