在向量中存储对象时的不良行为
Undesired behavior when storing object in vector
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
struct Node {
string name;
vector<Node> nodes;
Node(const string & name) : name(name) {}
~Node() {
cout << "release " << name << endl;
}
};
Node root {"A"};
unordered_map<string, Node*> m;
void add_child(const string & parent, const string & child) {
if (!m.count(parent)) return;
auto & p = *m[parent];
cout << "add " << parent << endl;
// Here is the bug
p.nodes.emplace_back(child);
m[child] = &p.nodes.back();
cout << "add done " << parent << endl;
}
int main() {
m["A"] = &root;
vector<string> edges {"A", "B", "A", "D", "B", "E"};
for (int i = 0; i < edges.size(); i += 2) {
add_child(edges[i], edges[i + 1]);
}
}
我正在构建一棵树,其中子节点直接存储为对象类型而不是指针类型。
每当我插入一个新节点时,我都会使用一个unordered_map来存储名称和对象指针的映射。
程序 运行 尝试访问 add_child
函数中插入的节点时失败并引发 BAD_ACCESS 异常。最后发现是因为B节点已经被删除了。我的问题是:这会在什么时候发生?
输出为:
add A
add done A
add A
release B
add done A
add B
Exception: EXC_BAD_ACCESS (code=1, address=0x100000010)
当调用push_back类函数时,向量auto-expand/reallocate之后的元素地址会变大space。
一种解决方案是将new
分配的地址存储在向量中,并在父节点被解构时将其全部删除。例如
struct Node {
string name;
vector<Node*> nodes;
~Node() {
for (auto pch : nodes)
delete pch;
}
};
root.nodes.push_back(new Node("child node"));
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
struct Node {
string name;
vector<Node> nodes;
Node(const string & name) : name(name) {}
~Node() {
cout << "release " << name << endl;
}
};
Node root {"A"};
unordered_map<string, Node*> m;
void add_child(const string & parent, const string & child) {
if (!m.count(parent)) return;
auto & p = *m[parent];
cout << "add " << parent << endl;
// Here is the bug
p.nodes.emplace_back(child);
m[child] = &p.nodes.back();
cout << "add done " << parent << endl;
}
int main() {
m["A"] = &root;
vector<string> edges {"A", "B", "A", "D", "B", "E"};
for (int i = 0; i < edges.size(); i += 2) {
add_child(edges[i], edges[i + 1]);
}
}
我正在构建一棵树,其中子节点直接存储为对象类型而不是指针类型。
每当我插入一个新节点时,我都会使用一个unordered_map来存储名称和对象指针的映射。
程序 运行 尝试访问 add_child
函数中插入的节点时失败并引发 BAD_ACCESS 异常。最后发现是因为B节点已经被删除了。我的问题是:这会在什么时候发生?
输出为:
add A
add done A
add A
release B
add done A
add B
Exception: EXC_BAD_ACCESS (code=1, address=0x100000010)
当调用push_back类函数时,向量auto-expand/reallocate之后的元素地址会变大space。
一种解决方案是将new
分配的地址存储在向量中,并在父节点被解构时将其全部删除。例如
struct Node {
string name;
vector<Node*> nodes;
~Node() {
for (auto pch : nodes)
delete pch;
}
};
root.nodes.push_back(new Node("child node"));