Runtime error with compile in VS2005, but not VS2002?

Started by
2 comments, last by KulSeran 18 years ago
Ok, so i have some code for the main loop of my program. The main point of it is to provide a system to regester modules that should be updated every game loop. This include stuff like an Audio system, Resource loader, Main game loop, Input ... While they are running, the modules get an update call. If the window loses focus, they should become paused. These system level modules get cleared out at the end of the program. So, why does this NOT crash on my computer(VS2002), but DOES crash when compiled on another system (VS2005 express). The crash only occurs on exit (alt-f4 or the X) and only when not in the debugger. Although it is not multi-threaded, it is acting like there is a race condidtion between removing something, and pausing it.

bool WinFinish ( )
{	
	bool rVal = true;

	for ( vector<Module *>::iterator x = modules.begin(); x != modules.end(); x++ )
	{
		rVal &= (*x)->Destroy();
		delete (*x);
		modules.erase(x);
		x--;		//Crashes here.
		}
        return rVal;
        }

void  WinDoPause ( bool paused )
{
	for ( vector<Module *>::iterator x = modules.begin(); x != modules.end(); x++ )
	{
		(*x)->Pause(paused); //Or crashes here
		}
	}

These are the rutines where the system it gets called.

LRESULT CALLBACK WinProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//..stuff...
	case WM_ACTIVATE:
		if ( pauseonfocus )
		{
			appPaused = (wParam == WA_INACTIVE);
			WinDoPause ( appPaused );
			}
		break;
//...
//Windows main loop
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
//blah...
WinFinish();
//blah...

Any advice on how to track down this bug? and why it only happens with the 2005 compiler?
Advertisement
You should not call erase when iterating your vector.
Try to replace your code by:

bool WinFinish ( )
{
bool rVal = true;

for ( vector<Module *>::iterator x = modules.begin(); x != modules.end(); x++ )
{
rVal &= (*x)->Destroy();
delete (*x);
}
modules.clear();
return rVal;
}
After you call erase, you can't use that iterator any more because it's invalid.
There are many possible fixes (not tested, but at least resembling a possible solution) :
vector<Module *>::iterator x = modules.begin();while(x != modules.end()){	rVal &= (*x)->Destroy();	delete (*x);	x = modules.erase(x);}
vector<bool> Result;transform(modules.begin(), modules.end(), back_inserter<bool>(Result), mem_fun<bool, Module *>(&Module::Destroy));for_each(modules.begin(), modules.end(), mem_fun<void, Module *>(&Module::operator delete));return find(Result.begin(), Result.end(), false) == Result.end();
And I'm sure many other ways. Since it's a vector, though, I'd suggest skipping the solutions that erase one element at a time as that will likely cause tons of extra and entirely unneccessary work to take place. kratolp's solution is probably one of the best, but if you're often deleting and/or adding elements to random places in the vector, you might want to consider using a different data structre such as list or set.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Ok. So i made the change sugested by kratolp, but now the error is forced into
WinPause.
WinFinish is the only place any removals take place, and my AddTask function only does a push_back() onto the vector.
So I don't know how I can be losing a pointer or anything.
And again, it works both release and debug compiles on my computer, but not on my team-member's computer if he compiles it.
(distance is keeping me from just debugging on his computer. and I can't reproduce the error)

Extrarius? is the version you posted faster? or better in some way? or ammount to the same exact thing?

This topic is closed to new replies.

Advertisement