c++undefined-behaviorlibstdc++valarray

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


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++?


Solution

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