   SDL Simple State Machine Error
  Hi guys, it's my first post here and, inevitably, it's because I've got an error.My problem is that my program crashes when I try to change state to or from my game state.I've spent the last day trying to find the problem. The crash happens when I try to access the first function of the state I have just changed to (currentstate->logic()), although, of course, another error must occur before that to cause the crash. I have tested for the current state being a null pointer but it turns up nothing. I have managed to get the code working (only in debug mode) but with some of the code commented out (Mostly the SDL_Surfaces, I think) but then I put all the code back to post and have since changed it.Also, if it helps, the two other states (pause and intro) can switch between each other fine.Anyway, here's the relevant code:The Header file including class definitions, constructors, destructors and one line functions. Should it all be in the cpp file? The rest is, anyway.class StateResource;class StateBase;class StateGame;class StateOther;class StateOther2;class StateResource // not deleted when state is changed,{    // passed to the new state insteadprotected:   int m_nNextState;   int m_nCurrentState;public:   SDL_Surface *mpn_Player;    SDL_Surface *mpn_Projectile;   SDL_Surface *mpn_Other;   StateBase *mpn_cSavedState;   StateResource(int nStateID)   :m_nNextState(STATE_NULL), m_nCurrentState(nStateID), mpn_cSavedState(0)   { mpn_Player = LoadImage("moon.bmp"); mpn_Projectile = LoadImage("projectile.bmp"); mpn_Other = LoadImage("wall.bmp");   } int getNextState(){return m_nNextState;}   int getCurrentState(){return m_nCurrentState;} void SaveState(StateBase *State){mpn_cSavedState = State;}   void SetNextState(int nNextState);   void ChangeState();   void ChangeState(StateBase *CurrentState); ~StateResource()   { SDL_FreeSurface(mpn_Player); SDL_FreeSurface(mpn_Projectile); SDL_FreeSurface(mpn_Other); delete mpn_cSavedState;   }};class StateBase{public: virtual void Input() = 0;    virtual void Logic() = 0;   virtual void Render() = 0;   virtual void Misc() = 0; virtual ~StateBase(){}};class StateGame : public StateBase{protected:   Uint32 Background;    SDL_Event m_Event; FrameRate cFrameRate;   SimpleObject cMarker;   Player cPlayer;   StateResource *mpn_cState;   public:    StateGame(StateResource *pn_State)   :mpn_cState(pn_State), cFrameRate(100), cMarker(-1, -1, 0), m_Event(),   cPlayer(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 2, 10, 10)   {  Background = SDL_MapRGB(SCREEN->format, 10, 10, 10); cFrameRate.Restart();   } void Input();   void Logic();   void Render();   void Misc(){cFrameRate.Regulate();} ~StateGame(){}};class StateIntro : public StateBase{protected:   Uint32 Background;    SDL_Event m_Event;   StateResource *mpn_cState;   public:    StateIntro(StateResource *pnState)   :mpn_cState(pnState), m_Event()   { Background = SDL_MapRGB(SCREEN->format, 100, 100, 100);   } void Input();   void Logic(){}   void Render();   void Misc(){} ~StateIntro(){}};class StatePause : public StateBase // should only be changed to by StateGame{protected:   Uint32 Background;    SDL_Event m_Event;   StateResource *mpn_cState;   public:    StatePause(StateResource *pn_cState)   :mpn_cState(pn_cState), m_Event()   { Background = SDL_MapRGB(SCREEN->format, 200, 200, 200);   } void Input();   void Logic(){}   void Render();   void Misc(){} ~StatePause(){}};And the next bit: (cpp file)void StateResource::SetNextState(int nNextState){   if(m_nNextState != STATE_QUIT) m_nNextState = nNextState;}void StateResource::ChangeState(){   m_nCurrentState = m_nNextState;   m_nNextState = STATE_NULL;}void StateResource::ChangeState(StateBase *CurrentState){   if(m_nNextState != STATE_NULL && m_nNextState != m_nCurrentState)   { if(m_nNextState != STATE_QUIT) {    switch(m_nNextState)    {  case STATE_GAME: delete CurrentState;if(m_nCurrentState == STATE_PAUSE)   CurrentState = mpn_cSavedState;else CurrentState = new StateGame(this);  break;  case STATE_PAUSE: if(m_nCurrentState == STATE_GAME){   delete mpn_cSavedState;   SaveState(CurrentState);}else delete CurrentState;CurrentState = new StatePause(this);   break;    case STATE_INTRO:delete CurrentState;CurrentState = new StateIntro(this);    break;  default:throw("Changed State to nothing");break;    }; } ChangeState();   }}void StateGame::Input(){   while(SDL_PollEvent(&m_Event))   { cPlayer.PlayerInput(m_Event); switch(m_Event.type) {case SDL_QUIT:    mpn_cState->SetNextState(STATE_QUIT);   break;case SDL_KEYDOWN:   switch(m_Event.key.keysym.sym)   { case SDLK_ESCAPE:mpn_cState->SetNextState(STATE_PAUSE);    break; default:    break;   };   break;    default:  break;};   }    }void StateGame::Logic(){   cMarker.SetPosition(cPlayer.getDestX<float>(), cPlayer.getDestY<float>()); //cPlayer.ProjectileCollision();   cPlayer.Move(); //cPlayer.CollisionCheck();}void StateGame::Render(){   SDL_FillRect(SCREEN, NULL, Background); // black background   cMarker.Draw(mpn_cState->mpn_Projectile, SCREEN);   cPlayer.Draw(mpn_cState->mpn_Player, SCREEN);   cPlayer.DrawProjectiles(mpn_cState->mpn_Projectile, SCREEN);   if(SDL_Flip(SCREEN) == -1) throw("Problem flipping the screen");}void StateIntro::Input(){   while(SDL_PollEvent(&m_Event))   { switch(m_Event.type) {    case SDL_QUIT: mpn_cState->SetNextState(STATE_QUIT);  break;    case SDL_KEYDOWN:  switch(m_Event.key.keysym.sym)  {case SDLK_ESCAPE:   mpn_cState->SetNextState(STATE_GAME);   break;default:   break;  };    default:  break;  };   }}void StateIntro::Render(){   SDL_FillRect(SCREEN, NULL, Background);   if(SDL_Flip(SCREEN) == -1) throw("Problem flipping the screen");}void StatePause::Input(){   while(SDL_PollEvent(&m_Event))   { switch(m_Event.type) {    case SDL_QUIT: mpn_cState->SetNextState(STATE_QUIT);  break;    case SDL_KEYDOWN:  switch(m_Event.key.keysym.sym)  {case SDLK_ESCAPE:   mpn_cState->SetNextState(STATE_GAME);   break;default:   break;  };    default:  break;  };   }}void StatePause::Render(){   SDL_FillRect(SCREEN, NULL, Background);   if(SDL_Flip(SCREEN) == -1) throw("Problem flipping the screen");}and the main loop:Init();StateResource *pn_cState = new StateResource(STATE_INTRO);StateBase *pn_cCurrentState = new StateIntro(pn_cState);while(pn_cState->getCurrentState() != STATE_QUIT){pn_cCurrentState->Input();    pn_cState->ChangeState(pn_cCurrentState);   pn_cCurrentState->Logic();   pn_cCurrentState->Render();   pn_cCurrentState->Misc();}delete pn_cCurrentState;delete pn_cState;SDL_Quit();Ok, sorry if I've missed anything. And I hope those code tags work :/.Hope that's enough info :)And thanks in advance...[Edited by - Feral_Punctuation on May 16, 2010 11:13:32 AM]
  At one point you call 'delete mpn_cSavedState' but you don't null that pointer. Later on you may be setting the current state to that, which is an invalid pointer. Consider writing short wrapper functions for your state management that ensure the pointers are always valid or null, and to eliminate the risk of memory leaks.May I suggest a few more things while I'm here? - add more comments. You may think the code is clear to you, but as soon as you start posting on forums asking for help, it's no longer good enough for you to understand your code - other people have to understand it too. - adopt a consistent code standard - some of your variables start with lowercase letters, some with uppercase, some have type annotations, some don't. It makes it harder for people to see at a glance what your code does. - remove the SDL_Event object from each state. You don't need it there.;  Thankyou for the reply. I think I will redo it from scratch, partly for the reasons you said and partly because I want it to be more reusable (and working), making sure I enact your changes :)   