我编写了一个boost :: thread应用程序,我可能会根据valgrind / helgrind报告获得一些竞争条件 . 我想确定这些比赛的原因 .
该计划是:
#include <boost/thread.hpp>
boost::mutex myMutex;
boost::condition_variable myConditionalVariable;
bool functionWasRun = false;
void function()
{
{
boost::lock_guard<boost::mutex> lock(myMutex);
functionWasRun = true;
}
myConditionalVariable.notify_one();
//doSomething1();
}
int main()
{
boost::thread pThread(function);
//Wait for the thread to start
boost::unique_lock<boost::mutex> lock(myMutex);
while (!functionWasRun)
myConditionalVariable.wait(lock);
//doSomething2();
pThread.join();
}
对于这个简单的程序,valgrind / helgrind报告了以下错误:
== 10840 == Helgrind,一个线程错误检测器
== 10840 ==版权所有(C)2007-2013,以及OpenWorks LLP等人的GNU GPL .
== 10840 ==使用Valgrind-3.10.0.SVN和LibVEX;用-h重新运行版权信息
== 10840 ==命令:./ boost_network_test
== == 10840
== 10840 == ---主题公告--------------------------------------- ---
== == 10840
== 10840 ==线程#1是程序的根线程
== == 10840
== 10840 == ---主题公告--------------------------------------- ---
== == 10840
== 10840 ==线程#2已创建
== 10840 ==在0x6570EBE:克隆(clone.S:74)
== 10840 == by 0x4E44199:do_clone.constprop.3(createthread.c:75)
== 10840 == by 0x4E458BA:pthread_create @@ GLIBC_2.2.5(createthread.c:245)
== 10840 == by 0x4C30C90:??? (在/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so中)
== 10840 == by 0x547B3B8:boost :: thread :: start_thread_noexcept()(在/usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0中)
== 10840 == by 0x53CFCC:boost :: thread :: start_thread()(thread.hpp:180)
== 10840 == by 0x53D31B:boost :: thread :: thread <void(&)()>(void(&)())(thread.hpp:267)
== 10840 == by 0x53CA7B:main(main_test.cpp:20)
== == 10840
== 10840 == --------------------------------------------- -------------------
== == 10840
== 10840 ==线程#1在0x8A21E0读取大小为8时可能发生数据竞争
== 10840 ==持有的锁:无
== 10840 ==在0x432CEB:boost :: mutex :: lock()(mutex.hpp:113)
== 10840 == by 0x43D197:boost :: unique_lock <boost :: mutex> :: lock()(lock_types.hpp:346)
== 10840 == by 0x43C1A0:boost :: unique_lock <boost :: mutex> :: unique_lock(boost :: mutex&)(lock_types.hpp:124)
== 10840 == by 0x53CA9E:main(main_test.cpp:23)
== == 10840
== 10840 ==这与线程#2的前一次写入大小为8冲突
== 10840 ==持有的锁:无
== 10840 ==在0x432CF6:boost :: mutex :: lock()(mutex.hpp:113)
== 10840 == by 0x43BFE9:boost :: lock_guard <boost :: mutex> :: lock_guard(boost :: mutex&)(lock_guard.hpp:38)
== 10840 == by 0x53C9DE:function()(main_test.cpp:10)
== 10840 == by 0x53DAAA:boost :: detail :: thread_data <void()()> :: run()(thread.hpp:117)
== 10840 == by 0x547BA49:??? (在/usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0中)
== 10840 == by 0x4C30E26:??? (在/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so中)
== 10840 == by 0x4E45181:start_thread(pthread_create.c:312)
== 10840 == by 0x6570EFC:clone(clone.S:111)
== == 10840
== 10840 == --------------------------------------------- -------------------
== == 10840
== 10840 ==线程#1在0x8A21E0写入大小为8时可能发生数据竞争
== 10840 ==持有的锁:无
== 10840 ==在0x432CF6:boost :: mutex :: lock()(mutex.hpp:113)
== 10840 == by 0x43D197:boost :: unique_lock <boost :: mutex> :: lock()(lock_types.hpp:346)
== 10840 == by 0x43C1A0:boost :: unique_lock <boost :: mutex> :: unique_lock(boost :: mutex&)(lock_types.hpp:124)
== 10840 == by 0x53CA9E:main(main_test.cpp:23)
== == 10840
== 10840 ==这与线程#2的前一次写入大小为8冲突
== 10840 ==持有的锁:无
== 10840 ==在0x432CF6:boost :: mutex :: lock()(mutex.hpp:113)
== 10840 == by 0x43BFE9:boost :: lock_guard <boost :: mutex> :: lock_guard(boost :: mutex&)(lock_guard.hpp:38)
== 10840 == by 0x53C9DE:function()(main_test.cpp:10)
== 10840 == by 0x53DAAA:boost :: detail :: thread_data <void()()> :: run()(thread.hpp:117)
== 10840 == by 0x547BA49:??? (在/usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0中)
== 10840 == by 0x4C30E26:??? (在/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so中)
== 10840 == by 0x4E45181:start_thread(pthread_create.c:312)
== 10840 == by 0x6570EFC:clone(clone.S:111)
== == 10840
== == 10840
== 10840 ==对于检测到的和抑制的错误计数,请重新运行:-v
== 10840 ==使用--history-level = approx或= none来提高速度,at
== 10840 ==冲突访问信息准确性降低的代价
== 10840 ==错误摘要:来自2个上下文的2个错误(被抑制:15个来自15个)
请问您能帮我确定如何修复此程序?
该程序在Ubuntu 14.04LTS,x86_64,gcc ver上运行 . 4.8.2,libboost v.1.54,valgrind 3.10.0 . 我的原始程序是一个使用ActiveObject类的复杂应用程序,它已经被剥离到最低限度看比赛条件模式 .
此线程可能与Debug boost::thread application, high false positive rate类似,但涉及条件变量/互斥锁 .
3 回答
正如有人说幕后发生了一些奇怪的事情,现在我找到了原因 .
boost和POSIX变体中的代码都没有什么奇怪之处 . 要点是代码是在测试框架中使用 -fprofile-arcs 标志编译的,我将其用于代码覆盖(lcov) . 此标志正在检测程序并更改其行为 . 在我的情况下,程序中出现的任何对象(例如boost :: mutex)都会被检测,因此会干扰helgrind输出 . 当程序转换为POSIX线程时,所有对象都消失了 - 干扰也是如此,这就解释了为什么POSIX变体有效 .
请尝试记住:HELGRIND = NO -fprofile-arcs FLAG
好消息是你的程序是正确的 . valgrind报告的所有比赛都是误报(尽管在加入线程之前考虑解锁互斥锁 - 以后可能会让你头疼) .
我有OSX10.10所以必须从最新的trunk创建valgrind才能尝试这个 .
这是它给我的东西(下面的截断输出)
我用std :: thread / std :: mutex等重写了程序,并得到了类似的结果 .
截断输出:
...
这可能是
myConditionalVariable
上的竞争条件吗?如果是这样,下面将解决问题 .