Cuaox
Cuaox

Reputation: 69

Element K of an object pointer vector turns null after pushing N-th element into the vector from element K-1

I recently started to learn OpenGL. I had an idea of testing my skills
after each part of the learnopengl.com tutorials, and I am
currently after chapter https://learnopengl.com/Getting-started/Shaders

So I have created a simple pong game, and while debugging I have noticed strange behavior.
The game I have created crashes after some time, but always after one of the players gets a point.
It's important to note that each game object has an update function that I call every frame,
and I keep pointers to all of the game objects in a STL vector.

I have analysed a bit of the code and found nothing bad with it, so i fired up gdb and wrote some "std::cerr" information.
This is what I found out:
1. The game crashed while updating one of the objects (obj->update())
2. The game always crashed after new point was awarded to a player, making the game object pointers vector contain 32 elements. If I used GAMEOBJECTS.relocate(33) before the game started, the vector contained 33 elements while crashing.
3. The game crashed while updating the fifth Game Object from the vector. It must be noted here, that the ball object is number four, and Ball::update() contains the code which creates new GameObjects (points).


From these information I deduce, that when I create a new object, and push it's pointer to a vector, the vector has to relocate itself, because It doesn't have enough capacity.
This, in turn, leads to some strange memory-mess which I do not understand, as I'm just starting to learn c++ programming.
That is also what makes accessing the fifth element of the vector impossible.
I'm struggling to find a way to solve this problem, but my biggest concern is understanding WHY is this happening.

The code is too big to be pasted here, so I put it on github:
https://github.com/carul/opengl_pong

I will still describe what I think is the most important:

for(auto && obj : GAMEOBJECTS){
  obj->update();
  obj->draw(VBO);
}

So this is the loop I use to draw and update my game objects.
I think there is nothing special about it, other than It updates objects one after another.

void Ball::update(){
   ///...
   if(boundingLeft < -0.96f){
    this->setPosition(0.0f, 0.0f);
    this->speedmodif = 0.8f;
    this->angle = 0;
    Point * point = new Point(GL_STATIC_DRAW);
    point->create(POINT_DATA);
    point->indice(POINT_INDICES);
    point->setPlayer(2);
    point->name = "POINT";
    point->setPosition(0.93f - 0.03f*scorep2, 0.9f);
    scorep2++;
    GAMEOBJECTS.push_back(point);
  }
  if(boundingRight > 0.96f){
    this->setPosition(0.0f, 0.0f);
    this->speedmodif = 0.8f;
    this->angle = M_PI;
    Point * point = new Point(GL_STATIC_DRAW);
    point->create(POINT_DATA);
    point->indice(POINT_INDICES);
    point->setPlayer(1);
    point->name = "POINT";
    point->setPosition(-0.95f + 0.03f*scorep1, 0.9f);
    scorep1++;
    GAMEOBJECTS.push_back(point);
  }
  ///...
}

This is a fragment of the ball's update function. This piece of code is responsible for creating a new point. Ball is a derived class of class Object.
GAMEOBJECTS is defined like this:
std::vector<Object * > GAMEOBJECTS;

Sorry for a long post, I tried to provide all the information I have.
Big thanks for reaching this part of the text, and thank You for any help

Here is a screenshot of gdb and the game during the crash:
screenshot

Upvotes: 0

Views: 43

Answers (1)

Evg
Evg

Reputation: 26342

In this loop

for(auto && obj : GAMEOBJECTS) {
    obj->update();
    obj->draw(VBO);
}

obj is a reference to the vector's element. In update() you push_back() into GAMEOBJECTS. This operation invalidates obj reference if vector's capacity is not enough to accommodate the new element.

Upvotes: 2

Related Questions