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
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: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:Which seems to me to imply that
valarray
is a container falling under §26.2.1 General container requirementsTo me it looks like
std::begin
on an emptyvalarray
should be valid. On the other hand "Returns: An iterator referencing the first value in the array" could imply a precondition that thevalarray
must not be empty. So my only conclusion is that the standard should be more clear in this regard.