Event Troubles.

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
AlexL
Posts: 184
Joined: Tue Mar 02, 2004 6:06 pm
Location: Washington State

Event Troubles.

Post by AlexL »

Of late, I have been doing some final touches to one of my projects before release, adding the spit and shine if you will. As such, I have attempted to add a exit confirmation window to the play state instead of a harsh, and unexpected, exit if the wrong key is pressed; harsh as it may have been, I used it through testing without getting an error or crash of any kind.

Though now that I have decided to do things right, I am getting the error below from my debugger when trying to step through the application. Without the debugger, it will simply end the program without a crash warning when the user confirms quiting to the menu.
Unhandled exception at 0x30c2ee88 in project_Debug.exe: 0xC0000005: Access violation reading location 0x30c2ee88.
//---
In CCore::run method, on the while line.
I am at a true loss here of what I can do to resolve this problem I have found myself into. When sorting through all the pointers in the debugger, they all seem to be as they should, no empty pointers where they should be filled. If someone has a spare moment or three, I would very much appreciate it if you could look over the code below and tell me where I have gone awry. Thank you all in advance :)

Code: Select all

// Event method.
bool CPlayState::processEvents(irr::SEvent hEvent)
{
	// Process all key input.
	if(hEvent.EventType == irr::EET_KEY_INPUT_EVENT)
	{
		// Switch through key input.
		switch(hEvent.KeyInput.Key)
		{
		case irr::KEY_KEY_Q:
			getCore()->getDevice()->getCursorControl()->setVisible(true);
			if(bWindowVisible == false)
			{
				pWindowExit = getCore()->getGui()->addMessageBox(L"Exit?",L"Really exit current game?",true,irr::gui::EMBF_YES | irr::gui::EMBF_NO);
				bWindowVisible = true;
			}
			break;

		default:
			break;
		}
	}

	// Process all gui events.
	if(hEvent.EventType == irr::EET_GUI_EVENT)
	{
		// Switch through gui events.
		switch(hEvent.GUIEvent.EventType)
		{
		case irr::gui::EGET_MESSAGEBOX_YES:
			// Clear the scene manager and gui environment.
			getCore()->getSceneManager()->clear();
			getCore()->getGui()->clear();

			// Stop all playing audio.
			getCore()->getAudio()->stopAllSounds();

			// Change the current scene.
			getCore()->getStateManager()->setCurrentState("Menu");
			break;

		case irr::gui::EGET_MESSAGEBOX_NO:
			// Reset gui environment back to normal.
			bWindowVisible = false;
			getCore()->getDevice()->getCursorControl()->setVisible(false);
			break;

		default:
			break;
		}
	}

	return false;
}

Code: Select all

// Update method.
void CCore::run()
{
	while(pVideo != NULL && pDevice->run())
	{
		// Get the delta time.
		float fUpdateNow = pDevice->getTimer()->getTime();
		float fUpdateLast = 0;
		float fUpdateDelta = ((fUpdateNow - fUpdateLast) / 1000.0f);

		// Update the current state.
		if(pStateMgr->getCurrentState() != NULL)
			pStateMgr->getCurrentState()->update(fUpdateDelta);

		// Update the devices.
		if(pVideo->beginScene(true,true,irr::video::SColor(0,100,100,100)) != false)
		{
			pSceneMgr->drawAll();
			pGui->drawAll();
			pVideo->endScene();
		}

		// Update the time.
		fUpdateLast = fUpdateNow;
	}
}
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You say it crashes here?

Code: Select all

while(pVideo != NULL && pDevice->run()) 
If that is the case, then it is likely that pDevice was dropped. The pointer is probably pointing to the memory that the device used to be stored in, but the device has been destroyed.

You can set a breakpoint where the device is dropped and then press Q. If the device is dropped you'll hit the breakpoint before it crashes. If it is dropped after it will crash first. Either that, or you can set pDevice to NULL after it is dropped. Then you can just check for a NULL pointer in the debugger when it crashes.

Also, your calculation of fUpdateDelta is 'wrong'. Every time through the loop you create a new fUpdateLast variable that is initialized to 0. This makes fUpdateDelta equal to pDevice->getTimer()->getTime() / 1000.f which is probably the number of seconds elapsed since the system was booted. I think you actually want the elapsed time since the last update/render. If that is the case, you would want something more like this...

Code: Select all

   float fUpdateLast = pDevice->getTimer()->getTime();

   while(pVideo != NULL && pDevice->run()) 
   { 
      // Get the delta time. 
      float fUpdateNow = pDevice->getTimer()->getTime(); 
      float fUpdateDelta = ((fUpdateNow - fUpdateLast) / 1000.0f); 

      // ...

      fUpdateLast = fUpdateNow;
   }
Travis
Marek
Posts: 12
Joined: Sat Mar 31, 2007 7:34 pm

Post by Marek »

Another suggestion when it comes to pDevice being dropped before then, would be to evaluate the state of pDevice before continueing on. If it is dropped you should either delete the device handler, and reallocate the object (or just reallocate the object itself if possible ). But that error usually only occures when you try to do somthing with raw memory itself (Memory location to an object that isn't "new" or to somthing that has been deleted and not reallocated later etc).

Best way in my mind, would be:

Code: Select all

if(pDevice != ((void*)(0))) // Or NULL if you prefer to use that, some compilers do 
{
            //..Do while stuff here
}
else
{     
          //re-initialize pDevice and run while here
}
Sorry I didn't look over the code quite as well as I would have liked (infact, I don't honestly think you can 'new' any sort of irrlichtDevices, but just based on the error, I come to that conclusion) owing to the fact I need to go to work.
-- Marc
Chaos Studios: Lead Programmer
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Just a short note: Don't cast to void* and don't use NULL. In C++ you simply use 0. Only for plain C you have to use NULL.
Marek
Posts: 12
Joined: Sat Mar 31, 2007 7:34 pm

Post by Marek »

I'm used to doing it a mixture of the 3 ways. void* for structs, NULL for char's etc. But yes, you're right. It is old C practice to set the location of the memory a pointer points to as 0 memory.
-- Marc
Chaos Studios: Lead Programmer
Post Reply