Mam problem z segfault, którego nie mogę wymyślić. To od EntityManager
dla małego silnika gry, nad którym pracuję. Mogę dodać Ship Entity
, a statek może dodać 1 Bullet Entity
, ale może to nastąpić, jeśli spróbuję dodać więcej niż 1 Bullet
. Próbowałem to rozgryźć przez ostatni dzień. Poniżej znajduje się niewielki fragment rzeczywistego kodu.wektor usuwania 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;
}
W rzeczywistym kodzie, wszystko jest w ich własnych plików .h/.cpp, a zajęcia zamiast elemencie, ale problem jest taki sam. Wyjście jest `Dodawanie Bullet Bullet konstruktor // // Zakończony pętla nr 1 // // Dodawanie Bullet Bullet konstruktor // sygnału: SIGSEGV (usterki Segmentacja)
segfault dzieje się w EntityManager::update()
na linii entity->update();
.
'EntityManager' potrzebuje niestandardowych operacji przenoszenia, aby zaktualizować wskaźnik" menedżera "encji. – dyp
Po zaktualizowaniu elementów pętla ta dodaje więcej elementów, które unieważniają iteratory. Nie możesz dodać do swojego wektora, gdy jesteś w trakcie przechodzenia przez niego. – Galik
[Pisz gry, nie silniki] (http://geometrian.com/programming/tutorials/write-games-not-engines/) to dobra rzecz do przeczytania. To powiedziawszy, zamiast dodawać rzeczy natychmiast lub natychmiastowo niszczyć rzeczy, możesz opóźnić te operacje po pętli aktualizacji, poprzez zdarzenia lub cokolwiek, co uznasz za stosowne, aby nie unieważniało iteratorów. – aslg