Benny Abramovici
Benny Abramovici

Reputation: 582

invalid std::vector iterator

I started writing my own particle effect system for a game I'm working on in C++ and sfml. In my update method I am removing the particles which life time has expired while iterating the vector. I thought I was careful not to invalidate the iterator after erasing elements as you can see at the bottom of the method, but I'm getting the exec_bad_access code=1 or code=2. the exception always points to the erase(it) line. any ideas what might be wrong?

void ParticlesNode::updateCurrent(sf::Time dt)
{
   for(particleIterator it = _mParticles.begin(), end = _mParticles.end(); it != end;)
{
    // calculate new color RGBA
    float nr = it->color.r + it->colorDis.r * dt.asSeconds();
    float ng = it->color.g + it->colorDis.g * dt.asSeconds();
    float nb = it->color.b + it->colorDis.b * dt.asSeconds();
    float na = it->color.a + it->colorDis.a * dt.asSeconds();
    it->color = sf::Color{static_cast<Uint8>(nr),static_cast<Uint8>(ng),static_cast<Uint8>(nb),static_cast<Uint8>(na)};

    // new position
    it->pos = sf::Vector2f(it->pos.x + it->vel.x * dt.asSeconds(), it->pos.y + it->vel.y * dt.asSeconds());

    // new velocity by linear accelaration.
    float length = getLength(it->vel);
    float newLength = length + _mPData.accel * dt.asSeconds();
    float radians = cartesianToPolar(it->vel).y;

    it->vel = polarToCartesian(newLength, radians);
    // new velocity by gravity
    // new velocity by radial acceleration.


    // new remaining life time
    it->lifeSpan -= dt.asSeconds();
    if (it->lifeSpan <= 0)
       _mParticles.erase( it );
    else
        ++it;
 }
}

Upvotes: 2

Views: 377

Answers (1)

songyuanyao
songyuanyao

Reputation: 172874

After erase the iterator it becomes invalid, but it's still used for the next iteration.

You should assign it by the return value of erase, which refers to the iterator following the erased element.

it = _mParticles.erase( it );

And note that not only the iterator at the point for erase becomes invalid, all the iterators after that, including end() also become invalid. So you need to evaluate end() for every iteration, i.e. change the condition of for to

for(particleIterator it = _mParticles.begin(); it != _mParticles.end();)

Upvotes: 4

Related Questions