我有一个Dag类(Directed Acyclic Graph),它包含一个指向Node类对象的原始指针向量。此向量称为m_roots
,由所有没有后代的节点组成。 (但它们最多可以有两个父节点)Node对象形成各种二叉树。
节点的成员属性是:
int m_indiv;
Node * m_dad;
Node * m_mom;
std::vector<Node * > m_offsprings;
int m_generat;
因此虽然结构是非循环的,但我在两个方向都有指针。 Dag构造函数启动一个重复,它根据地图中包含的数据创建节点。这是经常性的部分:
void Node::recNode(const map<int, pair<int, int> > &mapPed, map<int, Node * > &mapDup, const vector <int> &sampleListe, vector<Node * > &sample)
{
if (find (sampleListe.begin(), sampleListe.end(), this->m_indiv) != sampleListe.end()) {
sample.push_back(this);
}
pair<int, int> parents;
if (parents.first!=0) { //0 is a reserved integer for missing data, pointer stay to NULL (nullptr)
if (mapDup.find(parents.first) == mapDup.end() || !(mapDup[parents.first])) {
m_dad=new Node(parents.first);
if (mapDup.find(parents.first) != mapDup.end()) {
mapDup[parents.first]=m_dad;
}
m_dad->recNode(mapPed, mapDup, sampleListe, sample);
}
else {
m_dad=mapDup[parents.first];
}
m_dad->m_offsprings.push_back(this); //add the pointer to this node in the dads list of offspring
}
//do the same for the second parent
if (parents.second!=0) {
if (mapDup.find(parents.second) == mapDup.end() || !(mapDup[parents.second]) ) {
m_mom=new Node(parents.second);
if (mapDup.find(parents.second) != mapDup.end()) {
mapDup[parents.second]=m_mom;
}
m_mom->recNode(mapPed, mapDup, sampleListe, sample);
}
else {
m_mom=mapDup[parents.second];
}
m_mom->m_offsprings.push_back(this); //add the pointer to this node in the moms list of offspring
}
}
我的Dag析构函数启动递归破坏:
Dag::~Dag()
{
for (int i(0); i<m_roots.size();++i) {
delete m_roots[i];
}
}
Node析构函数应该进行实际的破坏:
Node::~Node()
{
if(m_dad) {
Node* dummyD=m_dad;
for (int i(0); i<m_dad->m_offsprings.size();++i) {
if (m_dad->m_offsprings[i]) {
m_dad->m_offsprings[i]->m_dad=nullptr;
}
}
delete dummyD;
}
if(m_mom) {
Node* dummyM=m_mom;
for (int i(0); i<m_mom->m_offsprings.size();++i) {
if (m_mom->m_offsprings[i]) {
m_mom->m_offsprings[i]->m_mom=nullptr;
}
}
delete dummyM;
}
}
由于某些原因,这不起作用:我遇到了Seg Fault。 相应的Valgrind错误是:
InvalidRead Invalid read of size 8
Call stack:
/usr/include/c++/4.8/bits/stl_vector.h 646 0x411734: Node::~Node()
~/Dag.cpp 138 0x409E98: Dag::~Dag()
~/main.cpp 114 0x41062B: main
Address 0x18 is not stack'd, malloc'd or (recently) free'd
每行调试行时,它会在以下行中断:
for (int i; i<m_dad->m_offsprings.size();++i) {
第一次迭代后。 (在第一次调用~Dag()和第一次调用~Node()时。它从断开的for循环中的i刚刚从0变为1。
它早期打破这个事实使得它不太可能是Dag中的循环问题......
我还有一个&#39; __ in_charg&#39;函数参数是<optimized out>
(尽管-O0)。我不确定这意味着什么,但似乎Node* dummyD=m_dad;
没有被阅读......
我正在寻找它不起作用的原因,逻辑中的缺陷......我知道可以使用shared_ptr
为父母和weak_ptr
为后代完成。
注意:术语父/后代在某种程度上是字段特定的。在这里,我在&#34; bio&#34; sens:每个人只有一个妈妈和一个爸爸,但可以有0到n个后代。
答案 0 :(得分:2)
在Node::~Node()
函数中,似乎this
是m_offsprings
之一。所以在
for (int i(0); i<m_dad->m_offsprings.size();++i) {
if (m_dad->m_offsprings[i]) {
m_dad->m_offsprings[i]->m_dad=nullptr;
}
}
this->m_dad
变为nullptr
。之后,您尝试在m_dad->m_offsprings.size()
中取消引用它。
要解决此问题,请检查当前m_dad
m_offspring
的地址是否不等于this
。 (同样适用于m_mom
。)
答案 1 :(得分:0)
不是直接的解决方案,但我想更有帮助:如果可能的话,通过使用智能指针完全摆脱所有提到的问题
Node
{
int m_indiv;
Node * m_dad;
Node * m_mom;
std::vector<std::shared_ptr<Node> > m_offsprings;
int m_generat;
}
不,如果一个节点被破坏( - 并且它是指向后代的最后一个节点),所有后代析构函数都会自动被递归调用。因此,无需编写容易出错的代码。
答案 2 :(得分:0)
m_roots [0]和m_roots [1]共享同一个爸爸。 当你删除Node m_roots [0]时,它的&#39;爸爸和妈妈被删除,以及他们整个家庭&#34;。因此,m_roots [1]变成孤儿。