在基于迭代器的循环中增长向量在使用munmap_chunk()进行破坏时崩溃:无效指针,为什么



有人能解释一下当我使用基于迭代器的for循环而不是使用基于索引的for循环时,我的程序崩溃的原因吗?我怀疑这是因为每次都会评估基于索引的for(),而基于迭代器的for()语句不知何故没有。

我试图在一个向量上循环,当到达最后一个元素时,它就是我要寻找的元素,调整向量的大小,再添加一个元素。如果我使用push_backresize,崩溃没有区别。

这是玩具代码,作为一个学习经验的例子。我想知道为什么一个崩溃了,而另一个没有。

当调用向量的析构函数时出现错误munmap_chunk(): invalid pointer:时,以下代码崩溃

#include <iostream>
#include <vector>
int main() {
std::vector<int> exampleVector {0,1,2,3,4,5};
// iterator based loop
for (auto it = exampleVector.begin(); it != exampleVector.end(); ++it) {
if (*it == 5 && std::next(it) == exampleVector.end()) {
exampleVector.resize(exampleVector.size() + 1);
*std::next(it) = 999;
*it = 0;
}
}
return 0;
}

从clion调试窗口复制的堆栈:

__GI_raise 0x00007f8cd892ce97
__GI_abort 0x00007f8cd892e801
__libc_message 0x00007f8cd8977897
malloc_printerr 0x00007f8cd897e90a
munmap_chunk 0x00007f8cd8985ecc
__GI___libc_free 0x00007f8cd8985ecc
__gnu_cxx::new_allocator<int>::deallocate new_allocator.h:125
std::allocator_traits<std::allocator<int> >::deallocate alloc_traits.h:462
std::_Vector_base<int, std::allocator<int> >::_M_deallocate stl_vector.h:180
std::_Vector_base<int, std::allocator<int> >::~_Vector_base stl_vector.h:162
std::vector<int, std::allocator<int> >::~vector stl_vector.h:435
main main.cpp:5
__libc_start_main 0x00007f8cd890fb97
_start 0x000055f736f6aaca

此程序不:

#includee <iostream>
#include <vector>
int main() {
std::vector<int> exampleVector {0,1,2,3,4,5};
// indexed for loop
for (size_t i = 0; i < exampleVector.size(); ++i) {
if (exampleVector.at(i) == 5 and exampleVector.at(i) == exampleVector.back()) {
exampleVector.resize(exampleVector.size() + 1);
exampleVector.at(i + 1) = 999;
exampleVector.at(i) = 0;
}
}
return 0;
}

在Ubuntu 18.04上,你在执行apt install build-essential时会得到gcc的默认版本。

再次,寻找一个崩溃而不是另一个崩溃的原因。此外,这是否适用于基于范围的for循环?

调整std::vector的大小时,指向它的迭代器可能会失效。因此,调整大小后需要重置it

if (*it == 5 && std::next(it) == exampleVector.end()) {
exampleVector.resize(exampleVector.size() + 1);
it = std::next(exampleVector.begin(), exampleVector.size() - 2);
// ...
}

显然,索引只是ints,所以它们不存在无效的问题,所以您的第二个示例工作得很好。

对于基于迭代器的循环来说,Range for循环只是一种很好的语法,所以是的,它会遇到与第一个版本相同的问题。