TotT: Finding Data Races in C++
November 13th, 2008 | Published in Google Testing
For example, you ask each of your two interns to bring you a bottle of beer. This will usually result in your getting two bottles (perhaps empty), but in a rare situation that the interns collide near the fridge, you may get fewer bottles.
4 int bottles_of_beer = 0;
5 void Intern1() { bottles_of_beer++; } // Intern1 forgot to use Mutex.
6 void Intern2() { bottles_of_beer++; } // Intern2 copied from Intern1.
7 int main() {
8 // Folks, bring me one bottle of beer each, please.
9 ClosureThread intern1(NewPermanentCallback(Intern1)),
10 intern2(NewPermanentCallback(Intern2));
11 intern1.SetJoinable(true); intern2.SetJoinable(true);
12 intern1.Start(); intern2.Start();
13 intern1.Join(); intern2.Join();
14 CHECK_EQ(2, bottles_of_beer) Who didn't bring me my beer!?";
15 }
Want to find data races in your code? Run your program under Helgrind!
$ helgrind path/to/your/program
Possible data race during read of size 4 at 0x5429C8
at 0x400523: Intern2() tott.cc:6
by 0x400913: _FunctionResultCallback_0_0::Run() ...
by 0x4026BB: ClosureThread::Run() ...
...
Location 0x5429C8 has never been protected by any lock
Location 0x5429C8 is 0 bytes inside global var "bottles_of_beer"
declared at tott.cc:4
Helgrind will also detect deadlocks for you.
Helgrind is a tool based on Valgrind. Valgrind is a binary translation framework which has other useful tools such as a memory debugger and a cache simulator. Related TotT episodes will follow.
No beer was wasted in the making of this TotT.
Remember to download this episode of Testing on the Toilet and post it in your office.