[SOLVED]std::map error

Get answers to all your basic programming questions. No Ogre questions, please!
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

[SOLVED]std::map error

Post by drwbns »

I'm getting a map / iterator errors when calling getInputMessage() - I'm not sure whats wrong with the call or definiton, help please -

Code: Select all


#include "OISKeyboard.h"
#include "IInputMessage.h"
#include <map>

namespace GameEngine {

	typedef  std::map< OIS::KeyCode, IInputMessage > InputMap;
	typedef  std::map< OIS::KeyCode, IInputMessage > InputKeyEventMap;

	class InputTranslator {
		public:
			InputTranslator(){};
			~InputTranslator(){};

			const IInputMessage &getInputMessage(const OIS::KeyCode& keycode) {
				inputMessageMapIter = inputMessageMap.find(keycode);
				if (inputMessageMapIter == inputMessageMap.end()) return NULLEVENT;
				return (*inputMessageMapIter).second;
			}
			void mapInputMessage(OIS::KeyCode keycode, const IInputMessage& message) {
				inputMessageMap.insert(std::make_pair< OIS::KeyCode, IInputMessage >(keycode, message));
			}

		protected:
			static InputMap inputMessageMap;
			static InputMap::iterator inputMessageMapIter;

	};
	InputMap InputTranslator::inputMessageMap;
	InputMap::iterator InputTranslator::inputMessageMapIter;
}
Last edited by drwbns on Tue Apr 23, 2013 2:42 pm, edited 2 times in total.
User avatar
areay
Bugbear
Posts: 819
Joined: Wed May 05, 2010 4:59 am
Location: Auckland, NZ
x 69

Re: std::map error

Post by areay »

What is the error message?

Also, is it valid to return a reference to 'NULLEVENT'?? What is that exactly? What happened when you made your class simpler by removing bits until you got it to work
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

areay wrote:What is the error message?

Also, is it valid to return a reference to 'NULLEVENT'?? What is that exactly? What happened when you made your class simpler by removing bits until you got it to work
This is what happens on a keypress -
keyPress-error.png
NULLEVENT IS a IInputMessage - shown in code here

Code: Select all

// IInputMessage.h

namespace GameEngine {
	enum IInputMessage {
		// PLAYER
		RUNFORWARD,
		RUNBACKWARDS,
		WALKFORWARD,
		WALKBACKWARDS,
		DIVEFORWARD,
		JUMP,
		CRAWL,
		CROUCH,
		SPRINT,
		STRAFELEFT,
		STRAFERIGHT,	
		HOLSTER,
		DANCE,
		//AIRCRAFT
		THROTTLEUP,
		THROTTLEDOWN,
		PITCHUP,
		PITCHDOWN,
		TURNLEFT,
		TURNRIGHT,
		NULLEVENT,
		//ACTIONS
		USE,
		SHOOT,
		// DRIVING
		DRIVEFORWARD,
		DRIVEREVERSE,
		DRIVERIGHT,
		DRIVELEFT,
		DRIVEBRAKE
	};
}
You do not have the required permissions to view the files attached to this post.
Last edited by drwbns on Mon Apr 22, 2013 4:26 pm, edited 2 times in total.
User avatar
Faranwath
Halfling
Posts: 93
Joined: Mon Jul 09, 2012 2:19 pm
Location: Cuba
x 7

Re: std::map error

Post by Faranwath »

Could you post the code in which you use the iterator after having invoked getInputMessage?
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

Faranwath wrote:Could you post the code in which you use the iterator after having invoked getInputMessage?
I'm calling it in my game's KeyPress listener function, mPlayer is an IPlayer object -

Code: Select all

bool CharacterDemo::keyPressed( const OIS::KeyEvent &evt )
{
       // direct checking for these key presses
	if( evt.key== OIS::KC_P ) manNode->flipVisibility();
	if( evt.key== OIS::KC_O ) mTerrainGroup->unloadTerrain(0,0);
	if( evt.key== OIS::KC_I ) mTerrainGroup->loadAllTerrains();
       
        // Checking for mapped InputMessages using keycode for map lookup, this call causes the crash
	mPlayer->sendInputMessage(mPlayer->getInputTranslator()->getInputMessage(evt.key));
	return keyPressed(evt);
}
and here's IPlayer.h, mITranslator is created in the IPlayer constructor -

Code: Select all

namespace GameEngine {

	class IPlayer : public IGameObject {
	public:
		IPlayer(){
			// Add player components
			addComponent(new CHealth);
			mITranslator = new InputTranslator();
			// map keys here
			mITranslator->mapInputMessage(OIS::KC_W, RUNFORWARD);
			mITranslator->mapInputMessage(OIS::KC_S, RUNBACKWARDS);
			mITranslator->mapInputMessage(OIS::KC_A, STRAFELEFT);
			mITranslator->mapInputMessage(OIS::KC_D, STRAFERIGHT);
			mITranslator->mapInputMessage(OIS::KC_UP, DRIVEFORWARD);
			mITranslator->mapInputMessage(OIS::KC_RIGHT, DRIVERIGHT);
			mITranslator->mapInputMessage(OIS::KC_LEFT, DRIVELEFT);
			mITranslator->mapInputMessage(OIS::KC_DOWN, DRIVEREVERSE);
			mITranslator->mapInputMessage(OIS::KC_SPACE, JUMP);
			mITranslator->mapInputMessage(OIS::KC_E, DANCE);
			mITranslator->mapInputMessage(OIS::KC_Q, HOLSTER);
			mITranslator->mapInputMessage(OIS::KC_C, CROUCH);
			mITranslator->mapInputMessage(OIS::KC_RETURN, USE);
		};
		~IPlayer(){};

		void setCamera(Ogre::Camera * cam) { mCamera = cam; }

		void setActiveControllable(IControllable* controllable) { mActiveControllable = controllable; }
		IControllable * getActiveControllable() { return mActiveControllable; }

		void setDefaultControllable(IControllable * controllable) { mDefaultControllable = controllable; }
		IControllable * getDefaultControllable() { return mDefaultControllable; }

		void update() {
			/*
			if(engineMgr->isKeyDown(OIS::KC_W))
				SendInputMessage(MITranslator->getMessage(OIS::KC_W));
				*/
		}

		void sendInputMessage(const IInputMessage &message) {
			getActiveControllable()->receiveMessage(message);
		}

		InputTranslator * getInputTranslator() { return mITranslator; }

	private:
		Ogre::String mName;		

		Ogre::Camera * mCamera;
		InputTranslator * mITranslator;
		IControllable * mActiveControllable;
		IControllable * mDefaultControllable;
	};
}
User avatar
Faranwath
Halfling
Posts: 93
Joined: Mon Jul 09, 2012 2:19 pm
Location: Cuba
x 7

Re: std::map error

Post by Faranwath »

Which key did you press that makes the application crash? Dis you cover all possibilities when mapping keys to events inside IPlayer's constructor? Does mActiveControllable handle NULLEVENT? I mean, if getInputMessage returns that constant, will the controller properly handle such a case?
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

I'm pressing the Return key, currently I'm not doing anything with the InputMessages, because I'm trying to get around the crash cause first. I'm only covering which keys are relavant at this point, but I am covering these keys in IPlayer.h-

Code: Select all

		IPlayer(){
			// Add player components
			addComponent(new CHealth);
			mITranslator = new InputTranslator();
			// map keys here
			mITranslator->mapInputMessage(OIS::KC_W, RUNFORWARD);
			mITranslator->mapInputMessage(OIS::KC_S, RUNBACKWARDS);
			mITranslator->mapInputMessage(OIS::KC_A, STRAFELEFT);
			mITranslator->mapInputMessage(OIS::KC_D, STRAFERIGHT);
			mITranslator->mapInputMessage(OIS::KC_UP, DRIVEFORWARD);
			mITranslator->mapInputMessage(OIS::KC_RIGHT, DRIVERIGHT);
			mITranslator->mapInputMessage(OIS::KC_LEFT, DRIVELEFT);
			mITranslator->mapInputMessage(OIS::KC_DOWN, DRIVEREVERSE);
			mITranslator->mapInputMessage(OIS::KC_SPACE, JUMP);
			mITranslator->mapInputMessage(OIS::KC_E, DANCE);
			mITranslator->mapInputMessage(OIS::KC_Q, HOLSTER);
			mITranslator->mapInputMessage(OIS::KC_C, CROUCH);
			mITranslator->mapInputMessage(OIS::KC_RETURN, USE);
		};
User avatar
Faranwath
Halfling
Posts: 93
Joined: Mon Jul 09, 2012 2:19 pm
Location: Cuba
x 7

Re: std::map error

Post by Faranwath »

Try returning by value instead of by reference to const in getInputMessage.
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

still crashes at inputMessageMapIter = inputMessageMap.find(keycode); after changing the definition to -

Code: Select all

		const IInputMessage getInputMessage(const OIS::KeyCode& keycode) {
				inputMessageMapIter = inputMessageMap.find(keycode);
				if (inputMessageMapIter == inputMessageMap.end()) return NULLEVENT;
				return (*inputMessageMapIter).second;
			}
User avatar
saejox
Goblin
Posts: 260
Joined: Tue Oct 25, 2011 1:07 am
x 36

Re: std::map error

Post by saejox »

I have a few tests for you :D

Is the error deterministic? Happens at every keypress or only sometimes.
Is your application single threaded ?
Is your OIS.dll built with the same Visual Studio version as your game ?
Does it repeat when you change std::map to std::unordered_map ?
Nimet - Advanced Ogre3D Mesh/dotScene Viewer
asPEEK - Remote Angelscript debugger with html interface
ogreHTML - HTML5 user interfaces in Ogre
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58

Re: std::map error

Post by CABAListic »

Faranwath is right, though, returning by reference is incorrect, so you must return by value, or you will eventually get the next crash once you fixed this one.

Why do you use a static iterator in that function? Why not declare it locally?

In any case, you should probably use a debugger to look at the variables inside that function. I have a feeling that one of them is already corrupt (potentially the global map itself?), so your error might even be unrelated to this particular code. The debugger might help you to spot that corruption, and then you can work your way backwards to the actual root cause.
User avatar
Faranwath
Halfling
Posts: 93
Joined: Mon Jul 09, 2012 2:19 pm
Location: Cuba
x 7

Re: std::map error

Post by Faranwath »

The weird (or perhaps enlightening) part is that the exception is raised when creating the iterator. Here's my last shot: don't use references at all, pass messages by value (its'a an integer, after all). Also, the library seems to be throwing an exception. Did you try and catch it? Does its type tell you anything useful? I none of this works, perhaps some other user may give you more valuable insights :(
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

saejox wrote:I have a few tests for you :D

Is the error deterministic? Happens at every keypress or only sometimes.
Is your application single threaded ?
Is your OIS.dll built with the same Visual Studio version as your game ?
Does it repeat when you change std::map to std::unordered_map ?
Every keypress - 1st keypress
single threaded except for physics - Havok
OIS.dll is built with vc100, which is same version - vs2010
unordered map has same behaviour
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

CABAListic wrote: Why do you use a static iterator in that function? Why not declare it locally?
I was thinking maybe I had to make it static for some reason because I was running into this error. I get the same behaviour even without the static definitions, also the same behaviour with a locally defined iterator.

I tried removing all references like so but ending up with the same behaviour -

Code: Select all

			const IInputMessage getInputMessage(const OIS::KeyCode keycode) {
				InputMap::iterator inputMessageMapIter = inputMessageMap.find(keycode);
				if (inputMessageMapIter == inputMessageMap.end()) return NULLEVENT;
				return (*inputMessageMapIter).second;
			}
			void mapInputMessage(OIS::KeyCode keycode, const IInputMessage message) {
				inputMessageMap.insert(std::make_pair< OIS::KeyCode, IInputMessage >(keycode, message));
			}
User avatar
areay
Bugbear
Posts: 819
Joined: Wed May 05, 2010 4:59 am
Location: Auckland, NZ
x 69

Re: std::map error

Post by areay »

drwbns, I think you should do more work to identify the root of your problem.

Make a testing member function that you can call after you've created your object. Make it print out the size of the inputmap, then when you've got that working, expand it to iterate through the map printing out values (using a local scope iterator like Cabailistic mentioned). Eventually you'll find your smoking gun.
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

Ok I'll try that, thanks. Can you give an example of that? I used -

Code: Select all

std::cout << "mITranslator size: " << sizeof(mITranslator) << std::endl;
and it prints 4 as the size

I also print the InputMap size with every call like so -

Code: Select all

			const IInputMessage getInputMessage(const OIS::KeyCode keycode) {
				std::cout << "InputMap size : " << sizeof(inputMessageMap) << std::endl; // print size is always 56

				InputMap::iterator inputMessageMapIter = inputMessageMap.find(keycode);
				if (inputMessageMapIter == inputMessageMap.end()) return NULLEVENT;
				return (*inputMessageMapIter).second;
			}
Is it possible that this has something to do with the enormous amount of keypress captures? I'm only hitting the Return key once, but as you can see from my call stack picture, it's called many times over. Is this normal OIS behavior?
drwbns
Orc Shaman
Posts: 788
Joined: Mon Jan 18, 2010 6:06 pm
Location: Costa Mesa, California
x 24

Re: std::map error

Post by drwbns »

I found the cause, very stupid error - I was calling the keyPress function over and over in my derived class by saying return keyPress() instead of return BaseApplication::keyPress :roll: ....thanks for the help guys