C++ 双重释放或损坏(出)

标签 c++ vector stl

我在使用带有 vector STL 的迭代器时遇到了这个错误。

代码:-

#include <iostream>
#include <vector>

void print_vec(std::vector<int> vec)
{
    auto itr = vec.begin();
    while (itr != vec.end())
        std::cout << *itr++ << " ";
    std::cout << std::endl;
}

int main(int argc, char* argv[])
{
    std::vector<int> vals = { 1, 2, 3, 4, 5, 6 };
    print_vec(vals);
    auto it = vals.begin();
    vals.insert(it, 100);
    print_vec(vals);
    it += 4;
    std::cout << *it << "\n";
    vals.insert(it, 200);
    print_vec(vals);
    return 0;
}

输出:-
1 2 3 4 5 6 
100 1 2 3 4 5 6 
5
0 100 1 2 3 4 5 6 
double free or corruption (out)
Aborted (core dumped)

我不明白为什么会发生这种情况:修改 vector 后迭代器是否存在问题?我认为我对迭代器的直觉是有缺陷的。

最佳答案

当一个 std::vector调整大小时,迭代器变得无效,因为它在调整大小之前引用了 vector ,这可能包括将 vector 移动到不同的内存位置以保持连续性。在那种情况下 it不会自动更新以引用新位置。

这种情况下的结果(因为它是未定义的行为)是值 200没有插入 vector 中,但它被写入了 vector 先前占用的其他一些堆内存,该 vector 已被释放 - 即您损坏了堆。 vector 在从 main 退出时被销毁,此时系统堆管理失败并报告错误(事后)。

在插入之后重新分配迭代器可以解决问题:

it = vals.insert(it,100);
...

正如您所期望的那样,单个项目的输出报告 5 而不是 4,因为它只是读取尚未重用的旧 vector 内存并被其他内容覆盖。

您可以通过比较观察错误:
vals.insert(it,100);
std::cout<<std::distance(it,vals.begin())<<'\n' ;


it = vals.insert(it,100);
std::cout<<std::distance(it,vals.begin())<<'\n' ;

您的结果可能会有所不同,但在 https://www.onlinegdb.com/当我执行测试时,在第一种情况下,迭代器位置和 vector 开始之间的距离为 16 - 表明迭代器不再引用当前 vector 状态中的元素。在第二种情况下,距离为零 - 迭代器指的是新 vector 状态的开始。

如果vals的容量|在使用迭代器之前进行了扩展,例如:
vals.reserve(10);

然后单个元素的插入不会导致内存移动,并且不会发生故障-尽管不更新迭代器并不是一个好主意-它只是指示引擎盖下发生的事情。

关于C++ 双重释放或损坏(出),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60248976/

相关文章:

c++ - 找到数字属于哪个部分的快速方法是什么(在 C++ 中使用 vector )?

c++ - 这段代码有什么问题?

c++ - 迭代器的概念问题

c++ - 混合 C 和 C++ 代码时, main() 是否需要在 C++ 部分?

c++ - boost mutex, condition, scoped_lock ,我在这里用错了吗?

opengl - 向量 vec3 和 float 的 GLSL 总和

c++ - 将 C++ std::Vector 传递给 Python 中的 numpy 数组

c++ - 结束迭代器递减的可移植性如何?

c++ - 调整大小后指向元素值的 unordered_map 指针是否有效?

c++ - 在 armv7l (Odroid XU4) 上编译时出现 OpenCV "conflicting declaration"问题