Pieter
Pieter

Reputation: 32755

*iterator causes segfault

I'm trying to walk through a list. Here are some declarations:

list<CG1_Edge*> ActiveEdges;
list<CG1_Edge*>::iterator ActiveEdgeIterator;

Sometimes, this code segfaults on line 2:

for (this->ActiveEdgeIterator = this->ActiveEdges.begin(); this->ActiveEdgeIterator != this->ActiveEdges.end(); ++this->ActiveEdgeIterator) {
    CG1_Edge* currentEdge = *this->ActiveEdgeIterator;
    if (currentEdge->y_up < y)
        this->ActiveEdges.erase(this->ActiveEdgeIterator);
}

Are there any common reasons why this might result in a segfault?

Upvotes: 3

Views: 1181

Answers (2)

sehe
sehe

Reputation: 392921

Begemoth's comment should be the accepted answer. According to the standard erase invalidates "all iterator and references to elements after position"(my mistake; this was for vector and possibly other containers; so at least to avoid surprises you should do well to use the algorithm version instead).

So you'd be safer already using rbegin() and rend(). But why not use the std::alogirthms!

struct Predicate 
{
     int _y;
     explicit Predicate(int y) : _y(y) {}

     bool operator()(const CG1_Edge edge) const
     {
          return currentEdge->y_up < _y;
     }
};

std::erase(
     std::remove_if(this->ActiveEdges.begin(), this->ActiveEdges.end(), Predicate(y)),
     this->ActiveEdges.end());

Upvotes: 0

Mat
Mat

Reputation: 206689

You should use something like:

for (this->ActiveEdgeIterator = this->ActiveEdges.begin(); this->ActiveEdgeIterator != this->ActiveEdges.end(); ) {
    CG1_Edge* currentEdge = *this->ActiveEdgeIterator;
    if (currentEdge->y_up < y)
        this->ActiveEdgeIterator = this->ActiveEdges.erase(this->ActiveEdgeIterator);
    else
        ++this->ActiveEdgeIterator;
}

since erase returns an iterator positionned at the next element.

(Note: having that iterator as a member looks strange.)

Upvotes: 5

Related Questions