C ++:奇怪的向量行为

时间:2013-05-16 18:49:15

标签: c++ vector segmentation-fault

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

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

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

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

1 个答案:

答案 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_ptrshared_ptr)作为列表。

或者您将合并功能更改为Node::mergeFrom(Node& node2),而不是重载+运算符。

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