I was playing around with std::valarray
and UndefinedBehaviorSanitizer, and noticed that std::begin
an empty std::valarray
causes undefined behavior. Here is the code:
#include <valarray>
int main() {
std::valarray<int> a;
std::begin(a);
}
To reproduce, compile the code with g++ -fsanitize=undefined
and run the result executable.
Here is the std::begin
implementation from libstdc++.
template<class _Tp>
inline _Tp*
begin(valarray<_Tp>& __va)
{ return std::__addressof(__va[0]); }
It seems that _val[0]
creates an reference of null value for empty std::valarray
s which causes the undefined behavior.
Is this a bug from libstdc++?
n4659 - C++17 final working draft
§26.2.1 General container requirements [container.requirements.general]
Table 83 — Container requirements
a.begin()
- no precondition
so a.begin()
must be valid on an empty container.
However valarray
is defined in §29.7 Numeric arrays [numarray] from the §29 Numerics library [numerics] chapter so it's not directly part of the container library chapter.
The std::begin(valarray)
is defined in §29.7.10 valarray range access [valarray.range] and here there is no mention of preconditions. Most relevant quotes hare are:
§ 29.7.10 valarray range access [valarray.range]
The iterators returned by
begin
andend
for an array are guaranteed to be valid until the member functionresize(size_t, T)
(29.7.2.8) is called for that array or until the lifetime of that array ends, whichever happens first.template <class T> unspecified 1 begin(valarray<T>& v); template <class T> unspecified 2 begin(const valarray<T>& v);
Returns: An iterator referencing the first value in the array.
So the question is if Table 83 applies here. valarray
is described in §29.7.2 Class template valarray [template.valarray] and the standard says:
29.7.2.1 Class template valarray overview [template.valarray.overview]
- The class template valarray is a one-dimensional smart array,
Which seems to me to imply that valarray
is a container falling under §26.2.1 General container requirements
To me it looks like std::begin
on an empty valarray
should be valid. On the other hand "Returns: An iterator referencing the first value in the array" could imply a precondition that the valarray
must not be empty. So my only conclusion is that the standard should be more clear in this regard.
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