【发布时间】:2015-09-25 09:55:55
【问题描述】:
我有一个无法解决的段错误问题。它来自EntityManager,用于我正在开发的小型游戏引擎。
我可以添加Ship Entity,Ship 可以添加1 个Bullet Entity,但如果我尝试添加超过1 个Bullet,则会出现段错误。在过去的一天里,我一直在试图弄清楚这一点。下面是实际代码的一小段摘录。
#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;
}
在实际代码中,一切都在它们自己的 .h/.cpp 文件中,并且是类而不是结构,但问题是一样的。 输出是`Adding Bullet // Bullet ctor // Completed Loop #1 // 添加 Bullet // Bullet ctor // Signal: SIGSEGV (Segmentation fault)
段错误发生在entity->update(); 行的EntityManager::update() 中。
【问题讨论】:
-
EntityManager需要自定义移动操作来更新实体的manager指针。 -
当您更新实体时,该循环会添加更多实体,从而使您的迭代器无效。当你在循环中时,你不能添加到你的向量中。
-
Write games not engines 是一本好书。也就是说,您可以通过事件或任何您认为合适的方式将这些操作延迟到更新循环之后,而不是立即添加或销毁,这样您就不会使迭代器无效。
-
首选
void add(std::unique_ptr<Entity> e)而不是void add(Entity* e)。 -
用于提供最小工作示例的道具。
标签: c++ segmentation-fault game-engine stdvector unique-ptr