我现在花了太多时间试图让以下代码段不是段错误。有人可以解释我为什么会这样做吗?
我知道问题出在某个未初始化的内存中。
#include <iostream>
#include <vector>
using namespace std;
struct node {
vector<int> parents;
};
int main() {
vector<node> nodedb;
{
node df;
nodedb.push_back(move(df));
}
{
node &existing_node = nodedb[0];
for (int i = 0; i < 100; ++i) {
node df;
nodedb.push_back(move(df));
existing_node.parents.push_back(0);
}
}
return 0;
}
答案 0 :(得分:5)
当你在循环中调用nodedb.push_back
时,这可能会使向量元素的现有指针/迭代器无效。如果向量需要增长超出其当前内存分配,则会发生这种情况 - 分配了一大块内存,复制了向量内容,并释放了旧内存。
这意味着在某些时候existing_node
变为无效,在此之后,取消引用它(通过existing_node.parents.push_back
)会导致崩溃。
有几种方法可以解决这个问题:
修改向量时,不要对向量元素进行引用 - 直接通过索引引用元素(即nodedb[0].parents.push_back
)。
正如@Neil Kirk上面所建议的那样,如果事先知道了向量的大小,那么在添加项目之前调用vector.reserve
意味着向量不需要重新分配内存,因为它增长。除了解决当前问题,这也将改善您的表现。但是,在更改矢量时保持对矢量项的引用仍然不是很好的做法。
正如@Greg Hewgill所指出的,您可以更改为使用list
而不是vector
,因为列表具有以下属性:列表元素的现有迭代器/引用不会被无效更改列表(除非这些元素本身被删除)。