I am interested to know if the MSVC compiler has any options that might have shown up the following bug the moment it was first written (over a year ago). In that time, the bug has been copied and pasted to several other places in the code. By rights that should have caused crashes every few seconds. By luck, it only crashes every few hours instead, and it usually leaves very little evidence to debug. The essence of the buggy code was something like:
int someDataSubjectToMultiThreadAccess;
CCriticalSection someSyncObject;
...
int SomeFunction( void )
{
CSingleLock( someSyncObject, TRUE );
return someDataSubjectToMultiThreadAccess;
}
I'm not going to highlight the error - the Visual Studio compiler certainly doesn't! If you can't see the error, create a test file, compile it, and look at the .cod file to see the assembler generated. With my optimisation settings, it calls the CSingleLock
constructor to create a temporary object, then immediately calls the corresponding destructor, which (through optimisation?) is the CSingleLock::Unlock()
function. Finally, the shared data is accessed without actually being locked.
So this is a cautionary tale in how to create a completely ineffective locking mechanism by omitting the variable that would last throughout the scope of the function - CSingleLock vitalLockVariable( someLock, TRUE );
. It surprised me how many eyes had seen this code and not noticed the bug.
I'll save you some of you the effort of typing this advice: "use the boost synchronisation primitives instead". Yes - thank you - one day I probably will. But this kind of slip probably applies to them equally well.
What I really want to know is what tools are available to catch this sort of thing, preferably the moment it is typed, but via any means other than code reviews or trying to analyse baffling crashes.