[C++] Vector subscript out of range

Hello,I’m writing a simple shoot em up in SFML (A C++ game making framework) and I’m having trouble implementing the shooting mechanic…

In my game I declared too classes,one for enemies called “enemy”,and one for the player’s projectiles called “projectile”.
I then declared 5 objects:

enemy basic_enemy1("res/images/enemy1.png", 70, 400); //Enemy objects
enemy basic_enemy2("res/images/enemy2.png", 100, 300);

std::vector <enemy> enemies; //Vector to store enemies in

projectile pprojectile("res/images/missile.png", { 10,30 }, 1000); //Player projectile object
std::vector <projectile> pprojectiles; //vector to store projectiles in

The two enemy objects are actually declared in a separate file,along with a method that randomly chooses one of them and adds it to the “enemies” vector every 2 seconds.

Projectiles are somewhat similar,except they’re spawned when the player holds “space”,and there’s only one object so all the work is done in the “main.cpp” file.

Then I wrote a condition so test if any of the projectiles and the enemies made contact,and delete them both from their respective vectors:

for (int i = 0; i < pprojectiles.size(); i++) {
			for (int j = 0; j < enemies.size(); j++) {
//This overly-complicated condition checks to see the projectile has entered the dimensions of the enemy
				if (((pprojectiles[i].m_shape.getPosition().y) <= ((enemies[j].es.getPosition().y) + enemies[j].es.getSize().y / 2))
					&& ((pprojectiles[i].m_shape.getPosition().x) >= ((enemies[j].es.getPosition().x) - enemies[j].es.getSize().x / 2))
					&& ((pprojectiles[i].m_shape.getPosition().x) <= ((enemies[j].es.getPosition().x) + enemies[j].es.getSize().x / 2))
					&& ((pprojectiles[i].m_shape.getPosition().y) >= ((enemies[j].es.getPosition().y) - enemies[j].es.getSize().y / 2))) {

					pprojectiles.erase(pprojectiles.begin() + i);//If true,erase projectile/This is the problematic line
					enemies.erase(enemies.begin() + j);//And erase enemy	
				}
			}
		}

Then there’s the lines that move and draw everything,with everything part of a loop that repeats every frame,no need to post those

So,for some odd reason,in certain cases,when an enemy and a projectile make contact,the game crashes,giving me the error in the title and screenshot…

Now I haven’t learnt how to debug a real-time interactive game yet,so the Visual Studio debugger can’t really help me pinpoint which line is causing this error,but after a bit of messing around with lines and values,I found it’s actually the line that erases the projectile in the condition above,I also found out that this error occurs when the enemy being hit with the projectile is relatively close to the player,like in he screenshot above.
Before,I thought it happened when there was only one projectile stored in the vector (Enemies/projectiles that go outside the screen are deleted using the same “erase();” function) but it’s inconsistent so I’m honestly not sure.

I know that this error means that the “i” index is moving outside the current range of the vector,but I don’t know why that happens,since the maximum value for the index is always limited by the current size of the vector,seen in the code above,plus,the enemy spawning/despawning process works almost identically to that of the projectiles,and it’s working just fine.

Any idea what might be causing this?

I haven’t dug into your code a lot. Have you tried to use Valgrind to get a stack trace on your errors?

You’re modifying the vectors you’re iterating over, namely shortening them. When you remove an element from the projectiles or enemies vector, it shifts all the remaining elements to the left by one, but you’ll still be looking at the same index, which is now the wrong element. When it’s the last projectile in the vector, your i index isn’t changed, but it’s looking past the end of the vector.

Don’t use .erase for this. Generally speaking, don’t add or remove entries from the thing you’re iterating over. Set the entry to null instead, and skip nulls gracefully. Or otherwise flag it as “dead”. Then periodically copy the projectiles and enemies vectors into new ones to process and eliminate the dead elements.

2 Likes

Ok I’ll look into how I can set a vector element to NULL,or ise the second method you mentioned,which is actually somewhat similar to how a cellular automata functions,where the 2D array being displayed is not the one where the calculations happen.
Understood,one of these two is bound to work,thank you!

EDIT: Ok,by creating two new objects of each type (enemy and projectile) that are basically empty placeholders,and replacing the “destroyed” elements with those as opposed to erasing them,the problem solved itself,once again,thank you.