Ho un problema con un segfault che non riesco a capire. È da un EntityManager
per un piccolo motore di gioco su cui sto lavorando. Posso aggiungere Ship Entity
e la Nave può aggiungere 1 Bullet Entity
, ma segfaults se provo ad aggiungere più di 1 Bullet
. Ho cercato di capire questo per il giorno passato ora. Di seguito è riportato un breve estratto dal codice reale.vettore dell'eliminazione unique_ptr?
#include <vector>
#include <memory>
struct EntityManager;
struct Entity {
Entity(EntityManager* manager) : manager(manager) { }
virtual ~Entity() { }
virtual void update() = 0;
EntityManager* manager;
};
struct EntityManager {
void update() {
for (auto& entity : entities) {
entity->update();
}
}
void add(Entity* e) {
entities.emplace_back(e);
}
std::vector<std::unique_ptr<Entity>> entities;
};
struct Bullet : public Entity {
Bullet(EntityManager* manager) : Entity(manager) { printf("Bullet ctor\n"); }
virtual void update() override { }
};
struct Ship : public Entity {
Ship(EntityManager* manager) : Entity(manager) { }
virtual void update() override {
printf("Adding Bullet\n");
manager->add(new Bullet(manager));
}
};
int main() {
EntityManager manager;
manager.add(new Ship(&manager));
int loops{0};
while (loops < 100) {
manager.update();
loops++;
printf("Completed Loop #%d\n", loops);
}
return 0;
}
Nel codice vero e proprio, tutto è nelle proprie file .h/cpp, e classi invece di struct, ma il problema è lo stesso. L'uscita è `Aggiungendo pallottola // pallottola ctor // completate Loop # 1 // Aggiunta pallottola // pallottola ctor // segnale: SIGSEGV (Segmentation fault)
Il segfault avviene nel EntityManager::update()
sulla linea entity->update();
.
'EntityManager' richiede operazioni di spostamento personalizzate per aggiornare il puntatore' manager' delle entità. – dyp
Quando aggiorni le entità, quel loop aggiunge più entità che invalida i tuoi iteratori. Non puoi aggiungere al tuo vettore mentre sei nel mezzo del looping. – Galik
[Scrivi giochi non motori] (http://geometrian.com/programming/tutorials/write-games-not-engines/) è una buona cosa da leggere. Detto questo, invece di aggiungere immediatamente le cose o distruggere le cose immediatamente, è possibile ritardare tali operazioni dopo il ciclo di aggiornamento, attraverso eventi o qualsiasi cosa si ritenga appropriata, in modo da non invalidare gli iteratori. – aslg