Is std::begin on an empty std::valarray undefined behavior?

219 views Asked by At

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::valarrays which causes the undefined behavior.

Is this a bug from libstdc++?

1

There are 1 answers

0
bolov On BEST ANSWER

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]

  1. The iterators returned by begin and end for an array are guaranteed to be valid until the member function resize(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);
    
  2. 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]

  1. 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.