奇怪的向量行为

C++: Strange vector behavior

本文关键字:向量      更新时间:2023-10-16

在为我的作业写代码时,我被一个奇怪的行为卡住了。代码太大,所以虽然没有必要,但我不会发布它。

事情是,当我试图从向量中删除一个对象时,我有一个分割错误。当我试着自己调试它时,我发现了这个:

如果我用下面的代码片段执行我的代码,我的vector为空,然后在第二行出现分段错误(因为vector为空)。

cout << this->adjacencyList.empty() << endl; // yeah, I'm working with graph
cout << *(this->adjacencyList[0]) << endl; // list has pointers

然而,当我删除第二行时,它显示vector不为空,然后继续。空向量的保护无法保持,导致分割错误。

你对这种行为有什么看法吗?如果这一点仍然模糊,我可以将我的完整代码作为编辑发布。

提前感谢。

编辑:

给那个要求"再多一点"的人。

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 - edge类声明

http://pastebin.com/C2DD6e3D - edge .cpp - edge类实现

http://pastebin.com/ZNqQ1iHE - node .h -节点类声明

http://pastebin.com/kaVtZ3SH - node .cpp - node类实现

http://pastebin.com/A7Fwsi4m - Network.h - graph类声明

http://pastebin.com/02LX0rjw - Network.cpp - graph类实现

http://pastebin.com/MRMn0Scz - main.cpp -示例main

我猜,存储在vector的第一个元素中的指针是无效的(可能是NULL ?)。

所以在this->adjacencyList[0]中没有出现分段故障,而在*(some_invalid_pointer)中出现。

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

来验证。

编辑

如果段错误发生在第一个语句(赋值)中,这意味着this无效,或者您设法破坏了属于vector内部的内存。为了验证这一点,我们必须看到处理adjacencyList的所有代码(我不确定是否有SO人有时间完成这项任务…)

注意

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

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

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

提示

如果你正在使用microsoftwinc++,你可以启用检查迭代器(见这里)。这些可能能够在你的代码中发现这类错误。

第二次编辑(响应代码)

你在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内)