Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a range specified by iterators is valid?

Many of the standard library containers have operations that accept a range specified by iterators. For example, std::list::assign(InputIterator first, InputIterator last).

But because many of these operations do not throw exceptions, if the range specified by [first,last) is not valid, it will cause undefined behaviour.

So what is a valid range? I assume it means that first comes before or is equal to last in the container, because when I tried otherwise (i.e. first comes after last), the program's execution would hang.

For example:

std::list.assign(container.begin(), container.end()); // valid range
std::list.assign(container.end(), container.begin()); // invalid range

Now with an assumption of what a valid range is, how can we check if a range is valid?

I came up with a helper function that checks if first is ever equal to last before it reaches the end of the container. If true, it's a strong guarantee that first does not come after last and therefore the range is valid.

template <typename Iterator>
bool isValidRange(Iterator first, Iterator last, Iterator end)
{
  for (; first != end; ++first)
    if (first == last) return true;
  return false;
}

It's not very convenient because you have to pass it an iterator to the end of the container in addition to the iterators that specify the range.

Is this correct? Is there a better way to do this?

like image 277
Dennis Avatar asked Aug 16 '13 05:08

Dennis


1 Answers

how can we check if a range is valid?

You can't. Your function cannot guarantee that the range is valid, only that the last is reachable from the first. These are two different things (for a simple example, consider an iterator into a vector which was subsequently reallocated). There is no mechanism by Standard that permits you to check if a range is valid. Much like you cannot know that a pointer is valid before you de-reference it.

Just to note, Microsoft provided a function to check if a pointer was valid and it utterly screwed everyone who used it. Raymond Chen said that it should have been named CorruptMemoryIfPossible.

like image 143
Puppy Avatar answered Sep 18 '22 02:09

Puppy