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.