简体   繁体   English

增加迭代器超出范围

[英]Incrementing iterator out of range

Is it illegal to increment random access iterator out of range? 将随机访问迭代器增加到超出范围是不合法的吗? It turns out that Visual C++ implementation of vector triggers debug assertion. 事实证明,Vector的C ++实现会触发调试断言。

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

This should be legal with pointers as long as memory location is not assessed. 只要不评估内存位置,这应该是指针合法的。

Edit: apparently it is illegal even with pointers. 编辑:显然即使使用指针它也是非法的。

It's undefined behavior. 这是未定义的行为。 Both with iterators and with pointers. 两者都有迭代器和指针。 With iterators, you'll probable get an assertion failure, at least with iterator debugging turned on. 使用迭代器,您可能会出现断言失败,至少在启用迭代器调试的情况下。 With pointers, it will probably do nothing in most modern architectures, but there have been machines on which it could trigger at trap. 有了指针,它在大多数现代架构中可能什么也不做,但是有一些机器可以在陷阱中触发。 You don't have to access the memory location itself, just create the pointer, for undefined behavior to occur. 您不必访问内存位置本身,只需创建指针即可发生未定义的行为。

EDIT: 编辑:

From the standard (§5.7/5, emphesis added): 从标准(§5.7/ 5,增加的假设):

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. 当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型。 If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. 如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。 In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i + n-th and i − n-th elements of the array object, provided they exist. 换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(等效地,N +(P))和(P)-N(其中N具有值n)指向分别为数组对象的第i + n和第i - 第n个元素,只要它们存在。 Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. 此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素。 If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; otherwise, the behavior is undefined . 否则, 行为未定义

The corresponding rule for random access iterators (the only ones which support addition) is spread-out over several sections: the += operator is defined in terms of repeated ++ (for the semantics—it is required to have constant time complexity), and ++ has the requirement that “pre: r is dereferenceable. 随机访问迭代器(唯一支持加法)的相应规则分布在几个部分: +=运算符是根据重复的++定义的(对于语义 - 它需要具有恒定的时间复杂度),和++要求“pre:r是可解除引用的。 post: r is dereferenceable or r is past-the-end.” (from the definition of input iterators, which is inherited by forward iterators, which is inherited by bidirectional iterators, which is inherited by random access iterators). post:r是dereferenceable或r是past-the-end。“(来自输入迭代器的定义,它由forward迭代器继承,由双向迭代器继承,由随机访问迭代器继承)。

This is undefined behavior, which means anything could happen, including segfault, or what you have experienced, or anything else. 这是未定义的行为,这意味着任何事情都可能发生,包括段错误,或您经历过的事情或其他任何事情。 Basically, you were just lucky it didn't crash (or unlucky, based on the point of view). 基本上,你很幸运它没有崩溃(或根据观点不吉利)。

The language does not require iterator accesses to be checked, as that would require a run-time check. 该语言不需要检查迭代器访问,因为这需要运行时检查。 C++ usually tries to avoid unnecessary run-time overhead, leaving the programmer to perform whatever checks are necessary. C ++通常会尝试避免不必要的运行时开销,让程序员执行必要的检查。

Most modern platforms use paged virtual memory, providing memory protection with a granularity of a few kilobytes. 大多数现代平台使用分页虚拟内存,提供几千字节的内存保护。 This means that there is often accessible memory after an allocated block (such as the one managed by std::vector), in which case out-of-range accesses will simply stomp on that memory. 这意味着在分配的块(例如由std :: vector管理的块)之后通常存在可访问的内存,在这种情况下,超出范围的访问将简单地踩在该内存上。

Visual Studio is trying to aid in removing dangerous code. Visual Studio正试图帮助删除危险的代码。 In principle a pointer could point anywhere if you didn't dereference it, but iterators are a higher level abstraction and have the ability to detect whether dereference would be valid and thus raise runtime errors. 原则上,如果您没有取消引用它,指针可以指向任何位置,但迭代器是更高级别的抽象,并且能够检测取消引用是否有效并因此引发运行时错误。 Visual Studio has done this with vector<T>::iterator at least since VS 2007. 至少自VS 2007以来,Visual Studio已经使用vector<T>::iterator完成了这项工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM