Out-of-range iterator increase

Is it wrong to increment a random access iterator out of range? It turns out that the Visual C ++ implementation of vector triggers debugs the statement.

std::vector<int> foo(5); auto iter = foo.begin(); iter += 10; 

This should be legal with pointers until memory is evaluated.

Edit: this seems to be illegal even with pointers.

+5
source share
2 answers

This behavior is undefined. Iterators and pointers. With iterators, you are likely to receive a rejection of the statement, at least with iterator debugging turned on. With pointers, this is likely to do nothing in most modern architectures, but there were machines on which it could be trapped. You do not need to access the memory location, just create a pointer for undefined behavior to occur.

EDIT:

From the standard (ยง5.7 / 5, embesis added):

When an expression with an integral type is added or subtracted from the pointer, the result is of the operand type of the pointer. If the pointer operand points to an element of the array object, and the array is large enough, the result indicates the offset of the element from the original element such that the difference between the indices of the resulting and initial elements of the array is equal to the integral expression. In other words, if the expression P points to the ith element of the array object, the expressions (P) + N (equivalently, N + (P)) and (P) -N (where N has the value n) indicates, respectively, I + n-th and in-th elements of the array object, if they exist. Moreover, if the expression P points to the last element of the array object, the expression (P) +1 indicates one after the last element of the array object, and if the expression Q indicates one after the last element of the array object, the expression (Q) -1 indicates the last element of the array an object. If both the pointer operand and the result point to elements of the same array object or one after the last element of the array object, the evaluation should not lead to overflow; otherwise, the behavior is undefined.

The corresponding rule for random access iterators (the only ones that have the addition of support) is divided into several sections: the += operator += defined in terms of repeated ++ (for semantics, constant time complexity is required), and ++ has the requirement that "pre: r is dereferenced. post: r is dereferenced or r is pass-through "(from the definition of input iterators that are inherited by cross iterators, which are inherited by bidirectional iterators, which are inherited by iterators arbitrary Foot access).

+3
source

This behavior is undefined, which means that everything can happen, including segfault or what you experienced, or something else. Basically, you are just lucky that it is not a failure (or unsuccessful, based on a point of view).

The language does not require an iterator access check, since this will require a run-time check. C ++ usually tries to avoid unnecessary overhead at runtime, leaving the programmer to perform any checks.

Most modern platforms use paged virtual memory, which provides memory protection with an accuracy of several kilobytes. This means that there is often available memory after the allocated block (for example, one controlled by std :: vector), in which case calls outside the range will simply stomp in that memory.

Visual Studio is trying to help remove dangerous code. Basically, a pointer could point anywhere if you hadn't dereferenced it, but iterators are a higher-level abstraction and have the ability to detect whether dereferencing is valid and, therefore, increase errors at runtime. Visual Studio has done this with vector<T>::iterator since at least VS 2007.

+2
source

Source: https://habr.com/ru/post/1212961/


All Articles