简体   繁体   English

C ++:奇怪的向量行为

[英]C++: Strange vector behavior

While writing code for my assignment, I have stuck on one strange behavior. 在为我的作业编写代码时,我一直坚持一种奇怪的行为。 The code is big, so while it is not necessary, I won't post it. 代码很大,所以虽然没有必要,但我不会发布它。

The thing is while I was trying to delete an object from the vector, I had a segmentation fault. 事情是,当我试图从矢量中删除一个对象时,我遇到了分段错误。 While trying to debug it myself, I have found this: 在尝试自己调试时,我发现了这个:

If I execute my code with the following snippet, I have my vector empty and then segmentation fault on the second line (since vector is empty). 如果我使用以下代码段执行我的代码,我的向量为空,然后在第二行上出现分段错误(因为向量为空)。

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

However, when I delete the second line, it shows that vector is not empty and then proceeds. 但是,当我删除第二行时,它显示向量不为空,然后继续。 The guard for empty vectors cannot hold it and segmentation fault comes. 空载体的保护不能保持它并且出现分段错误。

Do you have any ideas on this behavior? 你对这种行为有什么想法吗? If the point is still vague, I can post my full code as an edit. 如果这一点仍然含糊不清,我可以将我的完整代码发布为编辑。

Thanks in advance. 提前致谢。

EDIT: 编辑:

For the one who was asking "a little more". 对于那个问“多一点”的人。

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
}

SECOND EDIT: 第二次编辑:

NOTE: I cannot change headers (they were supplied by assistants), so don't ask me to change. 注意:我无法更改标题(它们由助手提供),所以不要让我改变。

If you are interested in a full code, you can find here 如果您对完整代码感兴趣,可以在这里找到

http://pastebin.com/iCYF6hdP - Exceptions.h - all exceptions http://pastebin.com/iCYF6hdP - Exceptions.h - 所有例外情况

http://pastebin.com/1fcgHGDa - Edge.h - edge class declaration http://pastebin.com/1fcgHGDa - Edge.h - 边缘类声明

http://pastebin.com/C2DD6e3D - Edge.cpp - edge class implementation http://pastebin.com/C2DD6e3D - Edge.cpp - 边缘类实现

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

http://pastebin.com/kaVtZ3SH - Node.cpp - node class implementation http://pastebin.com/kaVtZ3SH - Node.cpp - 节点类实现

http://pastebin.com/A7Fwsi4m - Network.h - graph class declaration http://pastebin.com/A7Fwsi4m - Network.h - 图表类声明

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

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

I would guess, that the pointer stored in the first element of your vector is invalid (perhaps NULL ?). 我猜,存储在向量的第一个元素中的指针是无效的(可能是NULL ?)。

So the segfault doesn't come up in this->adjacencyList[0] but in *(some_invalid_pointer) . 因此,segfault不会出现在this->adjacencyList[0]而是出现在*(some_invalid_pointer)

Try 尝试

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

to verify this. 验证这一点。

EDIT 编辑

If the segfault happens in the first statement (the assignment), this means, that either this is invalid or you somehow managed to corrupt memory belonging to the internals of vector . 如果段错误发生在第一个语句(赋值)中,这意味着, this是无效的,或者您以某种方式设法破坏属于vector内部的内存。 For this to verify, we would have to see all code that deals with your adjacencyList (and I'm not sure if SO people have the time for this task ...) 为了验证这一点,我们必须查看处理你的adjacencyList所有代码(我不确定SO人是否有时间完成这项任务......)

Note 注意

I've spotted a bug in the removeEdge , which is not directly related to your problem. 我发现了removeEdge一个错误,它与你的问题没有直接关系。 Within the loop, you use vector::erase to delete the current element. 在循环中,使用vector::erase删除当前元素。 This invalidates all iterators beyond the current one, so theoretically the rest of the loop is the infamous 'undefined behavior'(TM). 使得除当前迭代器之外的所有迭代器无效 ,因此理论上循环的其余部分是臭名昭着的“未定义行为”(TM)。 In this specific case (and supposing a 'normal' standard library), this will not result in a segfault but you might miss some elements: 在这种特定情况下(并假设一个'普通'标准库),这不会导致段错误,但您可能会遗漏一些元素:

If you delete the current element, the current iterator (normally simply a pointer) will point to the next element. 如果删除当前元素,则当前迭代器(通常只是指针)将指向下一个元素。 Then, the loop increment will move it to the element after this one resulting in one element not being checked. 然后,循环增量将把它移动到元素之后,导致一个元素未被检查。

If you have similar bugs in your code in other places, this might well result in memory corruption. 如果您在其他地方的代码中有类似的错误,这可能会导致内存损坏。

Tip 小费

If you're using Microsoft C++, you can enable checked iterators (see here ). 如果您使用的是Microsoft C ++,则可以启用已检查的迭代器 (请参阅此处 )。 These might be able to spot this kind of bugs in your code. 这些可能能够在您的代码中发现这种错误。

2nd EDIT (in response to code) 第二次编辑 (回复代码)

You have a serious error in the Node::operator+ . 你在Node::operator+有一个严重的错误。

Node &operator+ (Node &l, Node &r) // merges two nodes - for network merging
{
Node newNode (l.label);
    // Doing something
return newNode;
}

That means, you're returning a reference to a local variable , never do that :) ... 这意味着,您将返回对局部变量的引用从不这样做 :) ...

Note that, since you're using a vector of pointers, which are managed separately and released in the destructor, you cannot simply change the signature to Node operator+(... : in this case, the standard copy constructor would be called, which would simply copy all pointers to the result object. Then, the destructor of the local object would be called which would invalidate all pointers. 请注意,由于您使用的是指针向量,它们是单独管理并在析构函数中释放的,因此您不能简单地将签名更改为Node operator+(... :在这种情况下,将调用标准复制构造函数,将简单地复制所有指向结果对象的指针。然后,将调用本地对象的析构函数,这将使所有指针无效。

To fix this, you should implement a copy constructor on Node which makes real copies of all edges in the adjacency list. 要解决这个问题,你应该在Node上实现一个复制构造函数,它可以生成邻接列表中所有边的真实副本。

Alternatively, you could use smart pointers (either auto_ptr resp. unique_ptr or shared_ptr ) for the list. 或者,您可以使用智能指针( auto_ptr unique_ptrshared_ptr )作为列表。

Or you change the merge function to something like Node::mergeFrom(Node& node2) instead of overloading the + operator. 或者您将合并函数更改为Node::mergeFrom(Node& node2)而不是重载+运算符。

Concerning the original problem, you can easily end up working on an invalid Node instance using your current code (so the *this -Pointer would be invalid inside removeEdge ) 关于原始问题,您可以轻松地使用当前代码处理无效的Node实例(因此*this -Pointer在removeEdge无效)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM