Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] RenderWindow::draw() crashes program when iterating over an entity list  (Read 2498 times)

0 Members and 1 Guest are viewing this topic.

Storm_ReSurge

  • Newbie
  • *
  • Posts: 2
  • Freedom with a pinch of equity
    • View Profile
    • Email
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

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

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++.
« Last Edit: October 12, 2016, 09:51:00 am by Storm_ReSurge »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
AW: RenderWindow::draw() crashes program when iterating over an entity list
« Reply #1 on: October 11, 2016, 01:28:36 pm »
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.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: RenderWindow::draw() crashes program when iterating over an entity list
« Reply #2 on: October 11, 2016, 11:59:11 pm »
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.
« Last Edit: October 12, 2016, 12:01:14 am by DarkRoku »
I would like a spanish/latin community...
Problems building for Android? Look here

Storm_ReSurge

  • Newbie
  • *
  • Posts: 2
  • Freedom with a pinch of equity
    • View Profile
    • Email
Re: RenderWindow::draw() crashes program when iterating over an entity list
« Reply #3 on: October 12, 2016, 09:49:51 am »
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  :) )