Vector.Erase(Iterator) Causes Bad Memory Access

Vector.erase(Iterator) causes bad memory access

You should do

itVid = videoObjects.erase(itVid);

Quote from cplusplus.com:

[vector::erase] invalidates all iterator and references to elements after position or first.

Return value: A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.

Update: the way you access the current element inside your condition looks rather strange. Also one must avoid incrementing the iterator after erase, as this would skip an element and may cause out-of-bounds errors. Try this:

for(itVid = videoObjects.begin(); itVid != videoObjects.end(); ){
if(itVid->isInside(ofPoint(tcur.getX(), tcur.getY()))){
itVid = videoObjects.erase(itVid);
} else {
++itVid;
}
}

Deleting last element in a std::vector of std::shared_ptr while iterating over it causes segmentation fault

Change:

v.erase(el_it);

To

el_it = v.erase(el_it); // don't do this yet, read below

Erasing invalidates iterators. The return value of erase is the valid iterator to the next element. So with what I wrote above you're skipping one element. I'd recommend this:

for (auto el_it = v.begin(); el_it != v.end();) {
auto el = *el_it;
if (el->age_ == 2) {
el_it = v.erase(el_it);
} else {
++ el_it;
}
}

EXC_BAD_ACCESS when using vector iterators?

I think:

it_found == it;
^^^^

should be:

it_found = it;
^^^

Otherwise you are dereferencing a iterator which does not point to anything valid.

Also, you might want to use the Remove-Erase Idiom.

Erase element in vector while iterating the same vector

In the line:

it2 = uc.erase(it2);

an element pointed by iterator it2 is removed from the vector, elements are shifted in memory in order to fill that gap which invalidates it2. it2 gets a new value and now points to the first element after the the removed one or the end of the vector (if removed element was the last one). This means that after erasing an element you should not advance it2. An alternative to proposed remove-erase idiom is a simple trick:

for(it2 = uc.begin(); it2 != uc.end();)
{
...
if(...)
{
it2 = uc.erase(it2);
}
else
{
++it2;
}
...
}

You can read more about this here.

Edit:
Regarding your comment, you can use a flag to pass the information whether an element has been erased or not, and you can check it when you get out from the inner loop:

for(it2=uc.begin(); it2 != uc.end();)
{
bool bErased = false;

for(it3 = c.begin(); it3 != c.end(); ++it3)
{
if(adjacencyMatris[(*it2).id][(*it3).id] == 0 )
{
B.id = (*it2).id;
it2 = uc.erase(it2);
bErased = true;
B.color = currentColor;
c.push_back(B);
break;
}
}

if(!bErased)
++it2;
}

After you've erased an element from uc you need to break from the inner loop. In the next iteration of the outer loop you'll be able to access the next element in the uc through a valid iterator.

Does std::vector::erase() really invalidate the iterator at the point of erase?

Dereferencing an invalidated iterator has undefined results. Your program may crash, it may stop with a runtime error or break in the debugger (if you are running a debug build with a debug version of the STL with iterator debugging/validation) and it may "seem to work", i.e., deliver the value that was erased from the collection.

This is because iterators MAY be implemented as just pointers. This is not necessarily the case, but defining behavior in this situation as undefined allows such an efficient and simple implementation. Invalid iterators implemented as pointers MAY still point to a valid memory location, which MAY still contain the value it previously contained, even though it is logically no longer part of the data structure (collection) it was a part of. There is no validation code which checks if the iterator is valid when it is dereferenced (except sometimes in debug builds).

This is both one of the characteristics strengths and one of the weaknesses of C++, as it gives your program better performance at the cost of stability and security in case your program does something undefined (due to a bug or using unvalidated user input).

deleting while iterating

A vector's erase() invalidates existing iterators, but it returns a new iterator pointing to the element after the one that was removed. This returned iterator can be used to continue iterating over the vector.

Your loop could be written like this:

vector< vector<Point> >::iterator track = tracks_.begin();
while (track != tracks_.end()) {
if (track->empty()) {
// if track is empty, remove it
track = tracks_.erase(track);
}
else {
//if there are points, deque
track->erase(track->begin());
++track;
}
}

Bad Acces Memory with map iterator

You are accessing invalidated iterator. Once you pass it to erase() it is no longer valid, so you cannot increment it in your for loop. See Iterator Invalidation Rules for more details on that.

Your loop should be structured like this to avoid accessing invalidated iterators:

for (Map::iterator it = documents.begin() ; it != documents.end() ; )
{
std::string s = * ( it->first);
Document dd = * (it->second);
std::cout << s << " || " << dd;
documents.erase(it++);
}

Though I really recommend you read more documentation and understand what is going on here. For example, see this.

Good Luck!

Error while using vectors iterators' after insert and erase

after inserting/erasing from std::vector all existing iterators are invalidated and should not be used (using them will lead to undefined behavior)

remember, that changing items contained by vector may lead to memory allocation etc., so old iterators can point to deallocated memory (like pointers)

So when you add lines you mention and reinitialize iterator - everything is ok. But after insert existing p is no longer valid.

Check paragraphs about 'iterator invalidation' in: http://en.cppreference.com/w/cpp/container/vector/erase and http://en.cppreference.com/w/cpp/container/vector/insert.

You might consider adding call to reserve to ensure that no reallocation happens on insert but in my opinion such code would still be error prone and harder to maintain.



Related Topics



Leave a reply



Submit