Reputation: 33
In my game I created a base class called Entity which I store in a set for processing. All my game objects derive from this class, and I have no problem adding the derived pointer types to the set in my initialization function.
The problem lies in adding new elements from within an Entity's Step()
function. Now, before I get too far into it I'll show you some simplified code:
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;
};
The functions Add and Remove in GameState simply add the argument e to the added
and removed
sets respectively. In the main loop (elsewhere in GameState), I move the elements from added
to entities
before processing and after processing I remove elements from removed
from entities
. This ensures that entities
is not modified during iteration.
The Add/Remove functions are very simple:
void GameState::Add(Entity* e)
{
added.insert(e);
}
void GameState::Remove(Entity* e)
{
removed.insert(e);
}
Every derived Entity is passed a pointer to GameState in it's constructor that it keeps as game
. So theoretically from the Step function I should be able to Add and Remove entities with a simple call like game->Remove(this);
, but instead I get a segfault. After a night of googling and coming up with nothing, I was able to work around (part of) the problem by implementing Entity::Destroy()
like so:
void Entity::Destroy()
{
game->Remove(this);
}
So my first question is: Why does this
work when I'm in the base class but not in the derived class?
Even more puzzling to me is Add()
. Why does Add(new Explosion(16,16,this))
work in GameState but game->Add(new Explosion(16,16,game))
doesn't work inside my object?
I ran it through gdb and it tells me:
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
The code that throws the error is:
_Link_type
_M_begin()
{ return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } //this line
So to sum it up I have no idea why my pointers break the STL... and I get that grave feeling that I'm missing something very basic and its causing all these headaches. Can anyone give me advice?
Upvotes: 2
Views: 1206
Reputation: 54290
Why does
Add(new Explosion(16,16,this))
work inGameState
butgame->Add(new Explosion(16,16,game))
doesn't work inside my object?
If that is the case then the only possible explanation is that the Entity
's game
member doesn't actually point to the GameState
. Check that it is being set properly on construction and verify before you use it.
This has nothing to do with std::set
. The problem is that you are using an std::set
that is part of a class that you are accessing via a corrupt pointer.
Upvotes: 1