3

在为我的作业编写代码时,我遇到了一种奇怪的行为。代码很大,所以虽然没有必要,但我不会发布它。

问题是当我试图从向量中删除一个对象时,我遇到了分段错误。在尝试自己调试时,我发现了这一点:

如果我使用以下代码段执行我的代码,我的向量为空,然后第二行出现分段错误(因为向量为空)。

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 - 样本主

4

1 回答 1

1

我猜想,存储在向量第一个元素中的指针是无效的(也许NULL?)。

所以段错误不会出现this->adjacencyList[0]*(some_invalid_pointer).

尝试

Edge* firstEdge = this->adjacencyList[0];
cout << *firstEdge << endl;

来验证这一点。

编辑

如果段错误发生在第一条语句(赋值)中,这意味着要么this是无效的,要么你以某种方式设法破坏了属于vector. 为了验证这一点,我们必须查看所有处理您的代码adjacencyList(而且我不确定 SO 人是否有时间完成这项任务......)

笔记

我在 中发现了一个removeEdge与您的问题没有直接关系的错误。在循环内,您使用vector::erase删除当前元素。这会使当前迭代器之外的所有迭代器无效,因此理论上循环的其余部分是臭名昭著的“未定义行为”(TM)。在这种特定情况下(并假设一个“正常”标准库),这不会导致段错误,但您可能会错过一些元素:

如果删除当前元素,当前迭代器(通常只是一个指针)将指向下一个元素。然后,循环增量会将其移动到该元素之后的元素,导致一个元素未被检查。

如果您在其他地方的代码中有类似的错误,这很可能会导致内存损坏。

小费

如果您使用的是 Microsoft C++,则可以启用选中的迭代器(请参阅此处)。这些可能能够在您的代码中发现此类错误。

第二次编辑(响应代码)

你有一个严重的错误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_ptrresp.unique_ptrshared_ptr)。

或者您将合并函数更改为类似Node::mergeFrom(Node& node2)而不是重载+运算符。

Node关于原始问题,您可以轻松地使用当前代码处理无效实例(因此*this-Pointer 在内部无效removeEdge

于 2013-05-16T19:07:41.520 回答