简体   繁体   中英

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/1fcgHGDa - Edge.h - edge class declaration

http://pastebin.com/C2DD6e3D - Edge.cpp - edge class implementation

http://pastebin.com/ZNqQ1iHE - Node.h - node class declaration

http://pastebin.com/kaVtZ3SH - Node.cpp - node class implementation

http://pastebin.com/A7Fwsi4m - Network.h - graph class declaration

http://pastebin.com/02LX0rjw - Network.cpp - graph class implementation

http://pastebin.com/MRMn0Scz - main.cpp - sample main

I would guess, that the pointer stored in the first element of your vector is invalid (perhaps NULL ?).

So the segfault doesn't come up in this->adjacencyList[0] but in *(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 . 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 ...)

Note

I've spotted a bug in the removeEdge , which is not directly related to your problem. Within the loop, you use vector::erase to delete the current element. This invalidates all iterators beyond the current one, so theoretically the rest of the loop is the infamous 'undefined behavior'(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 ). 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 &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.

To fix this, you should implement a copy constructor on Node which makes real copies of all edges in the adjacency list.

Alternatively, you could use smart pointers (either auto_ptr resp. unique_ptr or shared_ptr ) for the list.

Or you change the merge function to something like Node::mergeFrom(Node& node2) instead of overloading the + operator.

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 )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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