c++ - 在基于迭代器的循环中增长向量在使用 munmap_chunk() 进行破坏时崩溃:无效指针,为什么?
问题描述
有人可以解释为什么我的程序在我使用基于迭代器的 for 循环而不是在我使用基于索引的 for 循环时崩溃的原因吗?我怀疑这是因为for()
每次都评估基于索引,而基于迭代器的for()
语句却不是。
我正在尝试遍历一个向量,当到达最后一个元素并且它是我正在寻找的一个元素时,调整向量的大小并添加一个更多元素。push_back
如果我使用or ,崩溃没有区别resize
。
这是玩具代码,例如学习经验。我想知道为什么一个崩溃而另一个没有。
当向量的析构函数被调用并出现错误时,以下代码会崩溃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
.
再次,寻找一个崩溃而不是另一个崩溃的原因。另外,这是否适用于基于范围的 for 循环?
解决方案
当您调整 a 的大小时std::vector
,指向它的迭代器可能会失效。所以调整大小后需要重新设置it
:
if (*it == 5 && std::next(it) == exampleVector.end()) {
exampleVector.resize(exampleVector.size() + 1);
it = std::next(exampleVector.begin(), exampleVector.size() - 2);
// ...
}
显然,索引只是int
s,所以它们变得无效没有问题,所以你的第二个例子工作正常。
Range-for 循环只是基于迭代器的循环的漂亮语法,所以是的,它与第一个版本有相同的问题。
推荐阅读
- python - Pandas - 计算列值大于阈值限制的连续行
- elasticsearch - 使用 Elasticsearch 和 NEST 从 id 返回以下五个文档
- javascript - 如何在 v-if 中呈现 axios 响应?还有其他方法吗?
- jmeter - 如何传递参数以跟随jmeter中的重定向?
- javascript - 获取 csv 文件并读取
- python - 使用 FastAPI 为使用 pycaret 生成的分类模型构建 API
- physics - 为什么我们不能在 Qiskit 的噪声模型基础门中添加“rx”(绕 X 轴旋转)和“ry”门?
- node.js - 为什么“git log”的输出在终端和node.js中的execSync不同
- javascript - Firestore 取消订阅不是一项功能
- javascript - 错误无法读取下拉侧边栏菜单上未定义的属性“包含”