Home > Back-end >  list.remove_if() crashing the program
list.remove_if() crashing the program

Time:07-24

I'm working on a game and I'm trying to add collectables. I'm trying to remove the object from the list after the player has collided with it, but it ends up crashing and says:

Unhandled exception thrown: read access violation. __that was 0xDDDDDDE9.

It says this on the for loop statement, but I think it has to do with the remove_if() function.

Here is my code:

for (sf::RectangleShape rect : world1.level1.brainFrag) {
        
        collides = milo.sprite.getGlobalBounds().intersects(rect.getGlobalBounds());
        
        if (collides == true) {
            world1.level1.brainFrag.remove_if([rect](const sf::RectangleShape val) {
                if (rect.getPosition() == val.getPosition()) {
                    return true;
                }
                else {
                    return false ;
                }
            });
            
            brainFrag -= 1;
            collides = false;
        }
        
    }
    if (brainFrag == 0) {
        milo.x = oldPos.x;
        milo.y = oldPos.y;
        brainFrag = -1;
    }

CodePudding user response:

I don't understand your approach, you loop the rects, then when you find the one you want to remove, you search for it again through list<T>::remove_if.

I think that you forgot about the fact that you can use iterators in addition to a range-based loop:

for (auto it = brainFrag.begin(); it != brainFrag.end(); /* do nothing */)
{
  bool collides = ...;

  if (collides)
    it = world1.level1.brainFrag.erase(it);
  else
      it;
}

This allows you to remove the elements while iterating the collection because erase will take care of returning a valid iterator to the element next to the one you removed.

Or even better you could move everything up directly:

brainFrag.remove_if([&milo] (const auto& rect) {
 return milo.sprite.getGlobalBounds().intersects(rect.getGlobalBounds())
}

A side note: there's no need to use an if statement to return a boolean condition, so you don't need

if (a.getPosition() == b.getPosition()
  return true;
else
  return false;

You can simply

return a.getPosition() == b.getPosition();
  • Related