首页 > 解决方案 > 在基于迭代器的循环中增长向量在使用 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 循环?

标签: c++

解决方案


当您调整 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);
     // ...
}

显然,索引只是ints,所以它们变得无效没有问题,所以你的第二个例子工作正常。

Range-for 循环只是基于迭代器的循环的漂亮语法,所以是的,它与第一个版本有相同的问题。


推荐阅读