Search code examples
c++sfml

list.remove_if() crashing the program


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;
    }

Solution

  • 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();