Reputation: 2524
I've got this piece of code:
for (std::vector<Marker>::iterator it = markers.begin(); it != markers.end(); ++it) {
if (it->getDots().size() < 3) {
markers.erase(it);
}
}
In one of test inputs (the app does image analysis) I get a segfault. I tried to debug the code (to no avail) and noticed one thing. When asking gdb to p markers.size()
i receive $9 = 3
. So I would expect the loop to iterate three times, but surprisingly it does it (at least) 5 times. In fifth iteration there's a segfault. What I also noticed is that it's not the dereference of *it
(here it->
) that causes the error. It's specifically it->getDots()
, which is a simple getter.
I write in C++ very rarely, so it might be some simple mistake, but neither my debugging, nor googling brought any solution. Could you help?
I'd like to emphasize, that on various different inputs (slightly different images) this function works properly, so it's even harder for me to trace the bug down.
Upvotes: 2
Views: 101
Reputation: 129524
You need to update it
when you erase:
it = markers.erase(it);
since erase
will "change" the vector
, and your current it
is no longer valid (and only do it++
if when you didn't erase it).
However, the more common way to do this is to use this type of construction:
markers.erase(std::remove(markers.begin(), markers.end(), number_in), markers.end());
Upvotes: 2
Reputation: 52621
vector::erase
invalidates all iterators pointing to the element being erased, and all elements that follow. So it
becomes invalid, and ++it
expression on the next loop iteration exhibits undefined behavior.
The best way to code this logic is with erase-remove idiom.
Upvotes: 6
Reputation: 8975
The problem is this line:
markers.erase(it);
The iterator is invalidated. But that's okay, erase
returns a valid iterator:
auto it = markers.begin();
while(it != markers.end())
{
if(it->getDots().size() < 3) {
it = markers.erase(it);
}
else ++it;
}
Upvotes: 3