1,105,578 Community Members

std::map insert crashes

Member Avatar
Dman01
Light Poster
30 posts since Aug 2010
Reputation Points: 10 [?]
Q&As Helped to Solve: 3 [?]
Skill Endorsements: 0 [?]
 
0
 

Hi community
First I want to thank everyone who will look through this, because it's a longer post.
I'm currently reading a book on AI by Mat Buckland.
I'm re-building Mats entitymanager, though I just copied it.
He used std::map to collect all entities as pointers which are cross referenced by their unique ID.
While I'm inserting such entity in a std::map the code fails and makes the program crash.
Because I can suppose it's a error from one of my class (since I'm doing a lot inheritance-stuff and with simple classes inserting works) I will post here my class tree of the entity-class I want to store in the map.

// A quik intro how my tree is build

// a class with drawing functions (SFML)
class gfxEntity 
// a base class for all entities (containing position velocity ...)
class BaseGameEntity : public gfxEntity 
// a class which should have AI and drawing methods
class BattleEntity : public BaseGameEntity

gfxEntity.h

#include "Render/Render.h"
#include "Render/GFXLIB.h"

class gfxEntity
{
protected : // Since inheritance must have access to it

    int m_iFrame;

    int m_iFrameIdleTime;

    float width,height;

    // Pixel holder
    sf::Sprite m_Sprite;
    sf::Image m_Image;
    BITMAP_RECTANGLE m_vFrameData[ FRAMES_MAX ]; //Contains 4 ints describing a rectangle

    // Points to the App, which allows us drawing methods (SFML)
    sf::RenderWindow* m_pRender;
    
    // Frame preparation will move the sprite to the correct position
    virtual void FramePreparation() = 0;
    // Calculates frames on an image and store them in Framedata
    virtual void InitialiseFrames() = 0;

    // Draws the sprite with currently selected frame
    virtual void Draw() = 0;

public:

    // The current frame will be selected to be drawn on screen
    void SetSub();
};

gfxEntity.cpp (Only defines SetSub) BaseGameEntity.h

class BaseGameEntity : public gfxEntity // inhertitates drawing functions
{
private :
    // ...
protected :
    // Is defined in the cpp
    virtual void FramePreparation();
    // Is dependent on the class => so leave modifyable
    virtual void InitialiseFrames() = 0;

public:

  // Can dependent on the class => same as above
  virtual void Draw();

  BaseGameEntity()
  {
    SetID(m_iNextValidID);
  }

  virtual ~BaseGameEntity(){}

  //all entities must implement an update function
  virtual void  Update()=0;

  //all entities can communicate using messages. They are sent
  //using the MessageDispatcher singleton class
  //NOT IMPLEMENTED YET
  virtual bool  HandleMessage(const Telegram& msg)=0;

BaseGameEntity.cpp

#include "Entity/BaseEntity.h"
void BaseGameEntity::FramePreparation()
{
    m_Sprite.SetPosition(m_vPosition.x,m_vPosition.y);
}

void BaseGameEntity::Draw()
{
    if (m_pRender) {
        // First set the position of the sprite
        FramePreparation();
        // Then draw it SFML-like
        m_pRender->Draw(m_Sprite);
    }
}

BattleEntity.h

class BattleEntity : public BaseGameEntity
{
private :
    // ...
protected :
    // No virtual since there will be no more inheritance above BattleEntity
    void FramePreparation();
    void InitialiseFrames();

    void Draw();
public :
    //this must be implemented (no more virtual)
    void Update();

    bool  HandleMessage(const Telegram& msg){return false;} // no more virtual

    ~BattleEntity(){delete m_pStateMachine;}

BattleEntity.cpp

#include "Entity/BattleEntity.h"

void BattleEntity::FramePreparation()
{
    BaseGameEntity::FramePreparation(); // No need to change the function yet
}

void BattleEntity::Draw()
{
    BaseGameEntity::Draw(); // No need to change the function yet
}

void BattleEntity::Update()
{
  m_pStateMachine->Update(); // AI thingies
  
  // Test if it works (should move slightly to the right)
  SetPosition(Position() + vec2(0.02f,0.0)); 
}

Whats not working :

typedef std::map<int, BaseGameEntity*> EntityMap;
EntityMap m_EntityMap;
//...
void EntityManager::RegisterEntity(BaseGameEntity* NewEntity)
{
    printf("INSERTING");

    std::pair<int,BaseGameEntity*> test = std::make_pair(NewEntity->ID(), NewEntity); // Works just fine

    m_EntityMap.insert(test); // Meh crashes no INSERTED is printed
    printf("INSERTED");
}

I am quite educated with inheritance with virtual methods but not well enough with std::maps, though I know std::vector well, which is kinda the same.
I am sure, that the error occurs because I use virtual function.

I'd really appreciate every tip on this error : D

If someone is interested , I uploaded this project on MU.
(www.megaupload.com/?d=DOUAFJEE)

Member Avatar
vijayan121
Posting Virtuoso
1,769 posts since Dec 2006
Reputation Points: 1,097 [?]
Q&As Helped to Solve: 329 [?]
Skill Endorsements: 16 [?]
 
0
 

> While I'm inserting such entity in a std::map the code fails and makes the program crash.
> Because I can suppose it's a error from one of my class

The crash doesn't seem have anything to do with inserting into a std::map<> per se.

a. in void EntityManager::RegisterEntity( BaseGameEntity* NewEntity )
validate that the pointer is not a nullptr, and then check the result of calling NewEntity->ID() on it.

b. If that gives a problem, write a simple console program to use as a test frame. For example,

#include <map>
#include <iostream>

struct BaseEntity
{
    virtual ~BaseEntity() {}
    virtual int ID() const = 0 ;
};

struct BattleEntity : BaseEntity
{
    virtual int ID() const /* override */
    {
        static int id = 100 ;
        return id += 7 ;
    }
} ;

std::map< int, BaseEntity* > map ;

void test_insert( BaseEntity* p )
{
    int id = p->ID() ;
    std::cout << "inserting object at: " << p << " with id: " << id << " ... " ;
    auto result = map.insert( std::make_pair( id, p ) ) ;
    if( result.second) std::cout << "inserted.\n" ;
}

int main()
{
    for( int i=0 ; i<10 ; ++i ) test_insert( new BattleEntity() ) ;

    for( const auto& pair : map )
        std::cout << pair.first << ' ' << pair.second << '\n' ;
}

Compile it and run it.
Then substitute your actual base class for BaseEntity and test it again.
Then substitute your actual derived classes one by one for BattleEntity, testing each one as you go along.

This way, you would be able to localize the error.

Member Avatar
Dman01
Light Poster
30 posts since Aug 2010
Reputation Points: 10 [?]
Q&As Helped to Solve: 3 [?]
Skill Endorsements: 0 [?]
 
0
 

Actually I do print out the address of the ptr plus the ID, both are working.
I tried putting a single BattleEntity in a <int,BasegameEntity*> in the main function, before my code starts. This time it's working, but when I use a map within my class it's crushing ... hmm I will go through my code further and tell when I find something.

Member Avatar
Dman01
Light Poster
30 posts since Aug 2010
Reputation Points: 10 [?]
Q&As Helped to Solve: 3 [?]
Skill Endorsements: 0 [?]
 
0
 

People , I'm sorry.
My mistake was to use the manager without initialisation.
Mr Buckland uses singleton's , what I totally missed.

@vijayan121
Thank you for leading me to the solution : D

@admins
I read alot about it, but is there no chance to move(or delete) this topic anywhere where it's hidden away, because this is a trash-thread since I only made a silly mistake and posted it ?

You
This article has been dead for over three months: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: