Элемент K вектора указателя объекта обнуляется после вставки N-го элемента в вектор из элемента K-1 - PullRequest
0 голосов
/ 17 мая 2019

Я недавно начал изучать OpenGL. У меня была идея проверить свои навыки
после каждой части уроков Learnopengl.com, и я в настоящее время
после главы https://learnopengl.com/Getting-started/Shaders

Итак, я создал простую игру в понг, и во время отладки я заметил странное поведение.
Созданная мной игра вылетает через некоторое время, но всегда после того, как один из игроков получает очко.
Важно отметить, что у каждого игрового объекта есть функция обновления, которую я вызываю каждый кадр,
и я сохраняю указатели на все игровые объекты в векторе STL.

Я немного проанализировал код и не нашел в нем ничего плохого, поэтому я запустил GDB и написал некоторую информацию "std :: cerr".
Вот что я узнал:
1. Игра упала при обновлении одного из объектов (obj-> update ())
2. Игра всегда зависала после начисления новой точки игроку, поэтому вектор указателей игровых объектов содержит 32 элемента. Если я использовал GAMEOBJECTS.relocate (33) до начала игры, вектор содержал 33 элемента при сбое.
3. Игра вылетела при обновлении пятого игрового объекта из вектора. Здесь следует отметить, что объект ball имеет номер четыре, а Ball :: update () содержит код, который создает новые GameObjects (points).


Из этой информации я делаю вывод, что когда я создаю новый объект и помещаю его указатель на вектор, вектор должен сам перемещаться, потому что у него недостаточно емкости.
Это, в свою очередь, приводит к некоторому странному беспорядку памяти, который я не понимаю, поскольку я только начинаю изучать программирование на С ++.
Это также делает невозможным доступ к пятому элементу вектора.
Я изо всех сил пытаюсь найти способ решить эту проблему, но моя самая большая проблема - понять, ПОЧЕМУ это происходит.

Код слишком велик, чтобы его можно было вставить здесь, поэтому я поместил его на github:
https://github.com/carul/opengl_pong

Я все еще опишу то, что я считаю наиболее важным:

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

Так что это цикл, который я использую для рисования и обновления своих игровых объектов.
Я думаю, что в этом нет ничего особенного, кроме того, что Он обновляет объекты один за другим.

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);
  }
  ///...
}

Это фрагмент функции обновления шара. Этот кусок кода отвечает за создание новой точки. Ball является производным классом класса Object.
GAMEOBJECTS определяется следующим образом:
std::vector<Object * > GAMEOBJECTS;

Извините за длинный пост, я пытался предоставить всю информацию, которую я имею.
Большое спасибо за то, что вы достигли этой части текста, и спасибо за любую помощь.

Вот скриншот gdb и игры во время аварии:
screenshot

1 Ответ

2 голосов
/ 17 мая 2019

В этом цикле

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

obj является ссылкой на элемент вектора.В update() вы push_back() в GAMEOBJECTS.Эта операция делает недействительной ссылку obj, если емкость вектора недостаточна для размещения нового элемента.

...