简体   繁体   English

取消引用一个超出范围的矢量迭代器 - 什么是开心的,为什么?

[英]Dereferencing an out-of-range vector iterator - what happpens and why?

Running this on my setup: 在我的设置上运行:

  vector<int> myvector;
  for (int i=1; i<=5; i++) myvector.insert(myvector.end(),i);

  vector<int>::iterator it;
  for ( it=myvector.begin() ; it < myvector.end()+2; it++ )
    cout << " " << *it;

Yields: 产量:

1 2 3 4 5 0 0 1 2 3 4 5 0 0

I would have thought that trying to dereference an out-of-range iterator would have resulted in a segfault. 我原本以为尝试取消引用超出范围的迭代器会导致段错误。 But it seems to yield an empty or default-initialized object of the type contained in the vector. 但它似乎产生了向量中包含的类型的空或默认初始化对象。

Is this well defined behaviour? 这是明确定义的行为吗? And where does this property come from, from the iterator or from the vector? 这个属性来自迭代器还是来自向量? Does the iterator in some sense catch the out-of-range-exception and instead return an empty object? 迭代器在某种意义上是否会捕获超出范围的异常,而是返回一个空对象?

I tried finding this in the C++11 reference, but it feels like it's a bit over my head. 我尝试在C ++ 11参考中找到这个,但感觉它有点过头了。

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). 基本上,你很幸运它没有崩溃(或根据观点不吉利)。

I would have thought that trying to dereference an out-of-range iterator would have resulted in a segfault. 我原本以为尝试取消引用超出范围的迭代器会导致段错误。

No, it gives undefined behaviour. 不,它给出了未定义的行为。 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管理的块)之后通常存在可访问的内存,在这种情况下,超出范围的访问将简单地踩在该内存上。

It may be possible to enable run-time iterator checks in your C++ library; 可以在C ++库中启用运行时迭代器检查; alternatively, tools such as valgrind or efence can help to debug various memory errors, including out-of-range accesses. 或者,诸如valgrindefence之类的工具可以帮助调试各种内存错误,包括超出范围的访问。

C++ Vector implementation is done using arrays- if the size exceeds, then it increases the size of underlying array: C ++ Vector实现是使用数组完成的 - 如果大小超过,那么它会增加底层数组的大小:
Here is some interesting code that Facebook had open sourced a while back- The comments on memory management are a great way to know more what goes under the hoods Facebook FBvector 这里有一些有趣的代码,Facebook已经开源了一段时间 - 关于内存管理的评论是一个了解更多内容的好方法Facebook FBvector

The result what you get is equivalent of out-of-bounds accessing of a 'C array' - random :-) 你得到的结果相当于访问'C数组'的越界 - 随机:-)

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

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