在为我的作业编写代码时,我一直坚持一种奇怪的行为。代码很大,所以虽然没有必要,但我不会发布它。
当我试图从矢量中删除一个对象时,我遇到了分段错误。在尝试自己调试时,我发现了这个:
如果我使用以下代码段执行我的代码,我的向量为空,然后在第二行显示分段错误(因为向量为空)。
cout << this->adjacencyList.empty() << endl; // yeah, I'm working with graph
cout << *(this->adjacencyList[0]) << endl; // list has pointers
然而,当我删除第二行时,它显示向量不为空,然后继续。 空载体的保护不能保持它并且出现分段错误。
你对这种行为有什么想法吗?如果这一点仍然含糊不清,我可以将我的完整代码发布为编辑。
提前致谢。
编辑:
对于那个问“多一点”的人。
void Node :: removeEdge (string destination) // removes an edge; edge is a class that contains a pointer to another node and its weight
{
bool deleted = false;
cout << *this << endl; // output stream operator is overloaded for node class and is working properly - shows it's label and edges - no error for an edge
cout << this->adjacencyList.empty() << endl;
// cout << *(this->adjacencyList[0]) << endl; // output stream operator is overloaded for edge class - error for an edge
if (!this->adjacencyList.empty())
{
for (vector <Edge *> :: iterator itr = this->adjacencyList.begin(); itr != this->adjacencyList.end(); ++itr)
{
if (((*itr)->getAdjacent())->getLabel() == destination) // segfault here
{
Edge *temp = *itr;
this->adjacencyList.erase (itr);
delete temp;
deleted = true;
}
}
}
if (!deleted)
throw EDGE_DOES_NOT_EXIST; // one of exceptions declared in enum somewhere in my code
}
第二次编辑:
注意:我无法更改标题(它们由助手提供),所以不要让我改变。
如果您对完整代码感兴趣,可以在这里找到
http://pastebin.com/iCYF6hdP - Exceptions.h - 所有例外
http://pastebin.com/1fcgHGDa - Edge.h - 边缘类声明
http://pastebin.com/C2DD6e3D - Edge.cpp - 边缘类实现
http://pastebin.com/ZNqQ1iHE - Node.h - 节点类声明
http://pastebin.com/kaVtZ3SH - Node.cpp - 节点类实现
http://pastebin.com/A7Fwsi4m - Network.h - 图表类声明
http://pastebin.com/02LX0rjw - Network.cpp - 图表类实现
http://pastebin.com/MRMn0Scz - main.cpp - 样本主
答案 0 :(得分:1)
我猜,存储在向量的第一个元素中的指针无效(也许是NULL
?)。
因此this->adjacencyList[0]
中的段错误不会出现在*(some_invalid_pointer)
中。
尝试
Edge* firstEdge = this->adjacencyList[0];
cout << *firstEdge << endl;
验证这一点。
修改强>
如果segfault发生在第一个语句(赋值)中,这意味着this
无效或者您以某种方式设法破坏属于vector
内部的内存。为了验证这一点,我们必须查看处理您adjacencyList
的所有代码(我不确定SO人是否有时间完成此任务...)
注意强>
我发现removeEdge
中存在一个与您的问题没有直接关系的错误。在循环中,使用vector::erase
删除当前元素。这个使所有迭代器无效超出当前的迭代器,因此理论上循环的其余部分是臭名昭着的“未定义行为”(TM)。在这个特定的情况下(并假设一个'普通'标准库),这不会导致段错误,但你可能会错过一些元素:
如果删除当前元素,则当前迭代器(通常只是一个指针)将指向下一个元素。然后,循环增量将把它移动到元素之后,导致一个元素未被检查。
如果您在其他地方的代码中有类似的错误,这可能会导致内存损坏。
提示
如果您使用的是Microsoft C ++,则可以启用已检查的迭代器(请参阅here)。这些可能会在您的代码中发现这种错误。
第二次编辑(以回应代码)
Node::operator+
。
Node &operator+ (Node &l, Node &r) // merges two nodes - for network merging
{
Node newNode (l.label);
// Doing something
return newNode;
}
这意味着,您将返回对本地变量的引用,从不这样做 :) ...
请注意,由于您使用的是指针向量,它们是单独管理并在析构函数中释放的,因此您不能简单地将签名更改为Node operator+(...
:在这种情况下,将调用标准复制构造函数,它只是复制所有指向结果对象的指针。然后,将调用本地对象的析构函数,这将使所有指针无效。
要解决这个问题,你应该在Node
上实现一个复制构造函数,它可以生成邻接列表中所有边的真实副本。
或者,您可以使用智能指针(auto_ptr
resp。unique_ptr
或shared_ptr
)作为列表。
或者您将合并功能更改为Node::mergeFrom(Node& node2)
,而不是重载+
运算符。
关于原始问题,您可以轻松地使用当前代码处理无效的Node
实例(因此*this
- 指针在removeEdge
内无效}