从向量中擦除时出现 C++ 分段错误
C++ Segmentation fault when erasing from vector
不是 iterate vector, remove certain items as I go 的重复,因为我已经尝试过该问题中使用的解决方案!
所以我正在制作一个游戏引擎,其中有一个名为 "Scene" 的 class,它有一个游戏对象向量。
场景有一个名为 "destantiate" 的函数,应该用于 "delete" 个游戏对象。
当我调用此函数时,我在尝试使用 std::vector::erase 函数时出现分段错误。
我认为这可能与另一个迭代向量的循环有关,它试图访问向量中已被删除的指针?
看看下面的代码:
#include "Scene.h"
#include "Instance.h"
Scene::Scene() {
this->camera = new Camera(0, 0);
}
void Scene::instantiate(Instance *instance) {
this->instances->push_back(instance);
}
void Scene::destantiate(Instance &instance) {
instance.trash = true;
}
void Scene::tick(float delta) {
this->camera->tick(delta);
for(std::vector<Instance*>::iterator it = this->instances->begin(); it != this->instances->end(); ++it) {
if ((*it)->trash) {
std::vector<Instance*>::iterator position = std::find(
this->instances->begin(),
this->instances->end(),
(*it)
);
if (position != this->instances->end()) {
this->instances->erase(position);
}
continue;
}
(*it)->collisionBox->width = (*it)->sprite->getCurrentImage()->getWidth();
(*it)->collisionBox->height = (*it)->sprite->getCurrentImage()->getHeight();
(*it)->tick(delta);
}
}
void Scene::draw(float delta) {
this->camera->draw(delta);
for(std::vector<Instance*>::iterator it = this->instances->begin(); it != this->instances->end(); ++it) {
if ((*it)->trash) { continue; }
glPushMatrix();
if ((*it)->centeredOrigo) {
glTranslatef((*it)->x - (*it)->sprite->getCurrentImage()->getWidth()/2, (*it)->y - (*it)->sprite->getCurrentImage()->getHeight()/2, 0.0f);
} else {
glTranslatef((*it)->x, (*it)->y, 0.0f);
}
if ((*it)->centeredOrigo) {
glTranslatef(((*it)->sprite->getCurrentImage()->getWidth()/2), ((*it)->sprite->getCurrentImage()->getHeight()/2), 0);
}
glRotatef((*it)->rotation, 0.0f, 0.0f, 1.0f);
if ((*it)->centeredOrigo) {
glTranslatef(-((*it)->sprite->getCurrentImage()->getWidth()/2), -((*it)->sprite->getCurrentImage()->getHeight()/2), 0);
}
(*it)->draw(delta);
glPopMatrix();
}
}
std::vector::erase 函数正在 "tick" 函数中调用,它检查对象是否具有 "trash" 标志。
这是运行时调用 "destantiate" 函数的地方,在游戏对象内部 class:
#include "SDLOpenGL.h"
#include "TestObj.h"
TestObj::TestObj(float x, float y) : Instance(x, y) {
this->sprite->addImage(game.loader->load("assets/card.png"));
this->centeredOrigo = true;
}
void TestObj::tick(float delta) {
if (this->trash) { return; }
//this->x = game.getMousePosition().x;
//this->y = game.getMousePosition().y;
this->rotation += 2.0f;
if (game.keyboardDown(SDL_SCANCODE_LEFT)) {
this->x -= 9.5f;
}
if (game.keyboardDown(SDL_SCANCODE_RIGHT)) {
this->x += 9.5f;
}
if (game.keyboardDown(SDL_SCANCODE_UP)) {
this->y -= 9.5f;
}
if (game.keyboardDown(SDL_SCANCODE_DOWN)) {
this->y += 9.5f;
//Segmentation fault
game.getCurrentScene()->destantiate(*this);
}
}
void TestObj::draw(float delta) {
if (this->trash) { return; }
this->sprite->draw(delta);
this->collisionBox->draw(delta);
}
输出:
Segmentation fault: 11
valgrind 说了一些关于 "use of uninitialized pointer"
我想你误解了我的意思。我会尝试用代码来解释:
void deinstantiate(GameObject go) {
flaggedForDeletion.push_back(go);
}
void tick(float delta) {
for(auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
it->tick(delta);
}
for(auto it = flaggedForDeletion.begin(); it != flaggedForDeletion.end(); ++it) {
std::remove(vec.begin(), vec.end(), *it);
}
}
因此,您只需存储要删除的对象,然后再删除它们。您不能在迭代它们时删除它们,因为它会使您的迭代器无效。
除了 this 解决方案适合您。
不是 iterate vector, remove certain items as I go 的重复,因为我已经尝试过该问题中使用的解决方案!
所以我正在制作一个游戏引擎,其中有一个名为 "Scene" 的 class,它有一个游戏对象向量。
场景有一个名为 "destantiate" 的函数,应该用于 "delete" 个游戏对象。
当我调用此函数时,我在尝试使用 std::vector::erase 函数时出现分段错误。
我认为这可能与另一个迭代向量的循环有关,它试图访问向量中已被删除的指针?
看看下面的代码:
#include "Scene.h"
#include "Instance.h"
Scene::Scene() {
this->camera = new Camera(0, 0);
}
void Scene::instantiate(Instance *instance) {
this->instances->push_back(instance);
}
void Scene::destantiate(Instance &instance) {
instance.trash = true;
}
void Scene::tick(float delta) {
this->camera->tick(delta);
for(std::vector<Instance*>::iterator it = this->instances->begin(); it != this->instances->end(); ++it) {
if ((*it)->trash) {
std::vector<Instance*>::iterator position = std::find(
this->instances->begin(),
this->instances->end(),
(*it)
);
if (position != this->instances->end()) {
this->instances->erase(position);
}
continue;
}
(*it)->collisionBox->width = (*it)->sprite->getCurrentImage()->getWidth();
(*it)->collisionBox->height = (*it)->sprite->getCurrentImage()->getHeight();
(*it)->tick(delta);
}
}
void Scene::draw(float delta) {
this->camera->draw(delta);
for(std::vector<Instance*>::iterator it = this->instances->begin(); it != this->instances->end(); ++it) {
if ((*it)->trash) { continue; }
glPushMatrix();
if ((*it)->centeredOrigo) {
glTranslatef((*it)->x - (*it)->sprite->getCurrentImage()->getWidth()/2, (*it)->y - (*it)->sprite->getCurrentImage()->getHeight()/2, 0.0f);
} else {
glTranslatef((*it)->x, (*it)->y, 0.0f);
}
if ((*it)->centeredOrigo) {
glTranslatef(((*it)->sprite->getCurrentImage()->getWidth()/2), ((*it)->sprite->getCurrentImage()->getHeight()/2), 0);
}
glRotatef((*it)->rotation, 0.0f, 0.0f, 1.0f);
if ((*it)->centeredOrigo) {
glTranslatef(-((*it)->sprite->getCurrentImage()->getWidth()/2), -((*it)->sprite->getCurrentImage()->getHeight()/2), 0);
}
(*it)->draw(delta);
glPopMatrix();
}
}
std::vector::erase 函数正在 "tick" 函数中调用,它检查对象是否具有 "trash" 标志。
这是运行时调用 "destantiate" 函数的地方,在游戏对象内部 class:
#include "SDLOpenGL.h"
#include "TestObj.h"
TestObj::TestObj(float x, float y) : Instance(x, y) {
this->sprite->addImage(game.loader->load("assets/card.png"));
this->centeredOrigo = true;
}
void TestObj::tick(float delta) {
if (this->trash) { return; }
//this->x = game.getMousePosition().x;
//this->y = game.getMousePosition().y;
this->rotation += 2.0f;
if (game.keyboardDown(SDL_SCANCODE_LEFT)) {
this->x -= 9.5f;
}
if (game.keyboardDown(SDL_SCANCODE_RIGHT)) {
this->x += 9.5f;
}
if (game.keyboardDown(SDL_SCANCODE_UP)) {
this->y -= 9.5f;
}
if (game.keyboardDown(SDL_SCANCODE_DOWN)) {
this->y += 9.5f;
//Segmentation fault
game.getCurrentScene()->destantiate(*this);
}
}
void TestObj::draw(float delta) {
if (this->trash) { return; }
this->sprite->draw(delta);
this->collisionBox->draw(delta);
}
输出:
Segmentation fault: 11
valgrind 说了一些关于 "use of uninitialized pointer"
我想你误解了我的意思。我会尝试用代码来解释:
void deinstantiate(GameObject go) {
flaggedForDeletion.push_back(go);
}
void tick(float delta) {
for(auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
it->tick(delta);
}
for(auto it = flaggedForDeletion.begin(); it != flaggedForDeletion.end(); ++it) {
std::remove(vec.begin(), vec.end(), *it);
}
}
因此,您只需存储要删除的对象,然后再删除它们。您不能在迭代它们时删除它们,因为它会使您的迭代器无效。
除了 this 解决方案适合您。