-
Hello.
I have a problem where if I were to use the draw function with the rectangle I got from iterating over a list of entities, the program would crash.
To be more specific, I have a struct for an entity, which will be added to a list to be updated/drawn:
typedef struct {
int type;
sf::Vector3f pos;
sf::Vector3f velocity;
sf::RectangleShape rect;
std::string name;
sf::Clock clock;
sf::Clock clock2;
int idx;
int total_health;
int health;
int state;
} Entity;
When I added the entities before game loop, it works just fine.
...
int main() {
Entity enemy {...};
ents.push_back(&enemy);
while (window.IsOpen()) {
...
for (Entity* e : ents) {
window.draw(e->rect);
}
...
}
}
However, if I were to add it during the main loop (and I mean anywhere in the loop), then it won't work anymore.
...
int main() {
int phase = 0;
while (window.IsOpen()) {
...
if (phase = 0) {
Entity enemy {...};
ents.push_back(&enemy);
phase = 1;
}
for (Entity* e : ents) {
window.draw(e->rect);
}
...
}
}
The debugger wasn't so informative on the problem either, but at least it says program crashes when it is trying to use the draw function like in the case above: https://i.imgsafe.org/cc0f93dfde.png (https://i.imgsafe.org/cc0f93dfde.png)
Initially, I thought it was a problem with adding/removing the elements when iterating over a vector, so I searched around and concluded that using a list instead would solve the problem. However, it seems to not be related since the program crashes when using either of the containers. So I tried another solution where I would add the entity to the list before iterating over it (the 2nd code snippet above), but that doesn't work either.
I suspected that the RectangleShape in the entities must somehow be null, but if that's actually the case then I don't know what would cause that either.
Here is the full source code just in case (the problematic lines are: 361, and 524): https://gist.github.com/sillyboyization/216b6898582c2d1ec6e0d22832be2d38 (https://gist.github.com/sillyboyization/216b6898582c2d1ec6e0d22832be2d38)
I would like to know if there is a mistake I made somewhere that I don't know about, because I've tried all the solutions I can think off the top of my head. I apologize in advance for the trouble; I'm new to C++.
-
Run it in debug mode and get the call stack of where the error originates from.
Looking at your code, I think you could clean up a lot if you used some classes.
-
your problem is here:
if (phase = 0)
{
Entity enemy {...}; //--> HERE
ents.push_back(&enemy);
phase = 1;
} //--> Entity is destroyed here, so the pointer to enemy is not valid anymore.
std::list<Entity*> ents; //--> You have a list of pointers, so your pointers need to be VALID.
for (Entity* e : ents) {
window.draw(e->rect); //--> Here your are drawing NULL pointers as a sf::RectangleShape
}
Solution:
if (phase = 0)
{
Entity *enemy = new Entity {...}; //--> The entity will be allocated on the heap.
ents.push_back(enemy);
phase = 1;
}
Remember to destroy the pointers when you don't need them.
Or try to use RAII in some way.
-
Thank you very much for all the tips and two cents! I was really up against a brick wall with this one, and never thought that would've been the problem.
So I was somewhat able to create a workaround with the solution: Create the Entities when loading each level (phase == 0), and then destroy anyone that dies.
...
if (phase == 0) {
Entity * tmp_ent = nullptr;
tmp_ent = new Entity {
...
};
ents.push_back(tmp_ent);
phase = 1;
}
...
for (Entity *rem : to_remove) {
ents.erase(std::remove(ents.begin(), ents.end(), rem), ents.end());
delete rem;
}
...
}
+1 to both (If this forums has reps, that is :) )