Heap corruption detected using std::vector in threaded app
Heap corruption detected using std::vector in threaded app
I have a multithreaded app that uses a single STL Vector to store pointers to all the game pieces in my game. I believe I have sufficiently surrounded all uses of this vector with locks. Additionally, when a particularly critical function uses this vector, I set the lock, make a local copy of the vector, unlock the lock and use the local copy. Occasionally when such a function returns I get a runtime error in dbgheap.c "HEAP CORRUPTION DETECTED" "CRT detected that the application wrote to memory after end of heap buffer.\n". Checking the call stack in the debugger reveals that this error originates as the function returns and the destructor on the local copy of the vector is called. Any ideas?
I certainly can't tell what possibly goes wrong in a multithreaded application without even seeing the code (a lot...). But the error could maybe simply be caused because you didn't allocate the memory for you local buffer before using it. Do you maybe copy using the [] operator and a loop? That would not resize the array and lead to that error.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
-
rogerborg
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Or you're copying the vector, but not the objects that the vector elements point to.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Sorry for not posting any code. It just seemed so spread out. I'm copying the vector using the =operator(http://www.cplusplus.com/reference/stl/ ... ator=.html) Here's some code:
Definition of the global vector:
Code to push a new game piece onto the vector:
Code that accesses the game piece vector and *sometimes* causes a HEAP corruption error:
Definition of the global vector:
Code: Select all
std::vector<GamePiece*> gpList;Code: Select all
{//Push onto gpList
int retryCount=0;
while( !lock_gpList.Lock() && retryCount++>MAXLOCKRETRY ){
Sleep(1);
}
if(retryCount>=MAXLOCKRETRY) {
std::stringstream logMsg;
logMsg<<"SafeLock.Lock(): Time out waiting for lock lock_gpList.";
WARNING_LOG(logMsg.str().c_str());
return false;
}
gpList.push_back(gp);
//printf("gpList.size:%u\n", gpList.size());
lock_gpList.Unlock();
}Code: Select all
std::vector<GamePiece*> gpList_local;
if( lock_gpList.Lock() ) {
gpList_local = gpList;
lock_gpList.Unlock();
}
else {
INFO_LOG("MapCamera::updateMap returning prematurely;");
return;
}I suppose any other access to gpList (like a call to clear()) is similarly protected. Then sorry, I don't see it :-(.
Though it could happen if your Lock() function is not threadsafe. How is that one implemented?
Though it could happen if your Lock() function is not threadsafe. How is that one implemented?
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Poorly. hehe. Here's the code:
Code: Select all
bool Lock(void)
{
if(!lock) {
lock=true;
return true;
}
else {
return false;
}
};
-
rogerborg
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Yup, that's about as useful as a chocolate teapot. A thread could get pre-empted immediately after it's checked "if(!lock")". You will have to use a native mutex (which will use a 'critical section' to prevent pre-emption), or an a cross platform library like pthreads.
Still, that'll only happen occasionally. You have another problem, which I am too sleep deprived to spot just now. I'll try again later.
Still, that'll only happen occasionally. You have another problem, which I am too sleep deprived to spot just now. I'll try again later.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
You may run into additional trouble because you have a vector of pointers to objects. After the assignment, both vectors will hold pointers to the same elements. If your other thread does anything with the elements themselves, then you will have a problem there also.
You could implement your 'lock' method with interlocked exchange [similar to what you are doing], but it isn't usually a good idea. It is probably best to use an actual lock primitive [CRITICAL_SECTION on Win32/64 and pthread_mutex_t on most *nix platforms] as pointed out by rogerborg in the previous post.
I'm actually curious why you decided to go ahead and use threads...
You could implement your 'lock' method with interlocked exchange [similar to what you are doing], but it isn't usually a good idea. It is probably best to use an actual lock primitive [CRITICAL_SECTION on Win32/64 and pthread_mutex_t on most *nix platforms] as pointed out by rogerborg in the previous post.
I'm actually curious why you decided to go ahead and use threads...
Hehe, thanks for the help thus far, folks. The irrlicht community is truly the best (most polite and helpful) I've ever encountered. I think i was a little confused by the threading situation. I had a thread for RakNet functionality and have now moved that functionality into the main thread. I thought the IEventReceiver.OnEvent() method I wrote for user input was in it's own thread, but it doens't appear to be so. Does anyone care to shed some light on how this function is called and whether or not it truly is in a seperate thread?
The event receiver OnEvent() method is called from the thread that you invoke device->run() in. Irrlicht is written to do everything from a single thread.
This has the advantage that it makes for a simple implementation and avoids any synchronization issues that could come up by adding threads. The disadvantage is that it isn't threaded...
Travis
This has the advantage that it makes for a simple implementation and avoids any synchronization issues that could come up by adding threads. The disadvantage is that it isn't threaded...
Travis