gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 15:13:29 28 4
gpt4 key购买 nike

我在使用带有 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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com