Segfault при использовании указателей std :: set ... кто-нибудь может это объяснить? - PullRequest
2 голосов
/ 13 августа 2011

В моей игре я создал базовый класс Entity, который я храню в наборе для обработки.Все мои игровые объекты происходят из этого класса, и у меня нет проблем с добавлением производных типов указателей к набору в моей функции инициализации.

Проблема заключается в добавлении новых элементов из в функции Step() сущности.Теперь, прежде чем я углублюсь в это, я покажу вам несколько упрощенный код:

class GameState
{
    public:
        GameState();
        ~GameState();
        ...
        set<Entity*> entities;
        void Add(Entity* e);
        void Remove(Entity* e);
    protected:
        set<Entity*> added, removed;
};

class Entity
{
    public:
        Entity();
        Entity(GameState* parent);
        virtual ~Entity();
        virtual void Step(const sf::Input& input);
        ...
        virtual void Destroy();
    protected:
        GameState* game;
};

Функции Add и Remove в GameState просто добавляют аргумент e к addedи removed комплектов соответственно.В основном цикле (где-то еще в GameState) перед обработкой я перемещаю элементы с added на entities, а после обработки удаляю элементы из removed из entities.Это гарантирует, что entities не изменяется во время итерации.

Функции Add / Remove очень просты:

void GameState::Add(Entity* e)
{
    added.insert(e);
}

void GameState::Remove(Entity* e)
{
    removed.insert(e);
}

Каждому производному объекту передается указатель на GameState в его конструкторе, который он сохраняет как game.Таким образом, теоретически из функции Step я должен иметь возможность добавлять и удалять сущности с помощью простого вызова, например game->Remove(this);, но вместо этого я получаю ошибку сегмента.После ночи поисков в Google и ничего не придумав, я смог обойти (частично) проблему, реализовав Entity::Destroy() следующим образом:

void Entity::Destroy()
{
    game->Remove(this);
}

Итак, мой первый вопрос: почему this работать, когда я нахожусь в базовом классе, но не в производном классе?

Еще более загадочным для меня является Add().Почему Add(new Explosion(16,16,this)) работает в GameState, но game->Add(new Explosion(16,16,game)) не работает внутри моего объекта?

Я запустил его через GDB, и он говорит мне:

Program received signal SIGSEGV, Segmentation fault.
At c:/program files (x86)/codeblocks/mingw/bin/../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:482

Код, который выбрасываетошибка:

_Link_type
  _M_begin()
  { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } //this line

Итак, подведя итог, я понятия не имею, почему мои указатели нарушают STL ... и у меня возникает такое серьезное чувство, что я упускаю что-то очень простое и вызывает все эти головные боли,Кто-нибудь может дать мне совет?

1 Ответ

1 голос
/ 13 августа 2011

Почему Add(new Explosion(16,16,this)) работает в GameState, но game->Add(new Explosion(16,16,game)) не работает внутри моего объекта?

Если это так, то единственно возможное объяснение состоит в том, что game член *1009* на самом деле не указывает на GameState. Убедитесь, что он правильно установлен на конструкцию, и проверьте, прежде чем использовать его.

Это не имеет ничего общего с std::set. Проблема в том, что вы используете std::set, который является частью класса, к которому вы обращаетесь через поврежденный указатель.

...