c++ - boost::thread 应用程序,奇怪的数据竞争报告

标签 c++ multithreading valgrind boost-thread

我编写了一个 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, a thread error detector
==10840== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.
==10840== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==10840== Command: ./boost_network_test
==10840== 
==10840== ---Thread-Announcement------------------------------------------
==10840== 
==10840== Thread #1 is the program's root thread
==10840== 
==10840== ---Thread-Announcement------------------------------------------
==10840== 
==10840== Thread #2 was created
==10840==    at 0x6570EBE: clone (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: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==10840==    by 0x547B3B8: boost::thread::start_thread_noexcept() (in /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== Possible data race during read of size 8 at 0x8A21E0 by thread #1
==10840== Locks held: none
==10840==    at 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== This conflicts with a previous write of size 8 by thread #2
==10840== Locks held: none
==10840==    at 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: ??? (in /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0)
==10840==    by 0x4C30E26: ??? (in /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== Possible data race during write of size 8 at 0x8A21E0 by thread #1
==10840== Locks held: none
==10840==    at 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== This conflicts with a previous write of size 8 by thread #2
==10840== Locks held: none
==10840==    at 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: ??? (in /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0)
==10840==    by 0x4C30E26: ??? (in /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== For counts of detected and suppressed errors, rerun with: -v
==10840== Use --history-level=approx or =none to gain increased speed, at
==10840== the cost of reduced accuracy of conflicting-access information
==10840== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 15 from 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但它涉及一个条件变量/互斥体。

最佳答案

好消息是你的程序是正确的。 valgrind 报告的所有竞争都是误报(尽管在您加入线程之前请考虑解锁互斥量 - 它可以让您以后省去麻烦)。

我有 OSX10.10,所以必须从最新的主干构建 valgrind 才能尝试这个。

这是它给我的(下面截断的输出)

我用 std::thread/std::mutex 等重写了程序,得到了类似的结果。

截断的输出:

==79537== Helgrind, a thread error detector
==79537== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.
==79537== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==79537== Command: Build/Products/Debug/cpprules
==79537== 
--79537-- Build/Products/Debug/cpprules:
--79537-- dSYM directory is missing; consider using --dsymutil=yes
--79537-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option
--79537-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times)
--79537-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times)
==79537== ---Thread-Announcement------------------------------------------
==79537== 
==79537== Thread #2 was created
==79537==    at 0x10048D7EE: __bsdthread_create (in /usr/lib/system/libsystem_kernel.dylib)
==79537==    by 0x10003FC75: boost::thread::start_thread_noexcept() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000134E: main (in Build/Products/Debug/cpprules)
==79537== 
==79537== ---Thread-Announcement------------------------------------------
==79537== 
==79537== Thread #1 is the program's root thread
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during read of size 4 at 0x1005AA2D8 by thread #2
==79537== Locks held: none
==79537==    at 0x10058FFCF: spin_lock (in /usr/lib/system/libsystem_platform.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 4 by thread #1
==79537== Locks held: none
==79537==    at 0x10058FFDF: spin_unlock (in /usr/lib/system/libsystem_platform.dylib)
==79537==    by 0x10003FC75: boost::thread::start_thread_noexcept() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000134E: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x1005aa2d8 is in the Data segment of /usr/lib/system/libsystem_pthread.dylib
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during read of size 4 at 0x103DEB010 by thread #2
==79537== Locks held: none
==79537==    at 0x1005A3293: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 4 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A30D8: pthread_create (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x10003FC75: boost::thread::start_thread_noexcept() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000134E: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x103deb010 is in a rw- mapped file segment
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during write of size 4 at 0x103DEB010 by thread #2
==79537== Locks held: none
==79537==    at 0x1005A329B: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 4 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A30D8: pthread_create (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x10003FC75: boost::thread::start_thread_noexcept() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000134E: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x103deb010 is in a rw- mapped file segment
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during write of size 4 at 0x1005AA2D8 by thread #2
==79537== Locks held: none
==79537==    at 0x10058FFDF: spin_unlock (in /usr/lib/system/libsystem_platform.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 4 by thread #1
==79537== Locks held: none
==79537==    at 0x10058FFDF: spin_unlock (in /usr/lib/system/libsystem_platform.dylib)
==79537==    by 0x10003FC75: boost::thread::start_thread_noexcept() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000134E: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x1005aa2d8 is in the Data segment of /usr/lib/system/libsystem_pthread.dylib
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during read of size 4 at 0x10004D118 by thread #2
==79537== Locks held: none
==79537==    at 0x100048451: boost::thread_detail::enter_once_region(boost::once_flag&) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10003FA54: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10003FD6C: boost::(anonymous namespace)::thread_proxy(void*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x1005A32FB: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 4 by thread #1
==79537== Locks held: none
==79537==    at 0x10004854A: boost::thread_detail::commit_once_region(boost::once_flag&) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10003F9F4: boost::detail::get_current_thread_data() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000139F: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x10004d118 is in the Data segment of /usr/local/lib/libboost_thread.dylib
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during read of size 8 at 0x10004D120 by thread #2
==79537== Locks held: none
==79537==    at 0x10003FA78: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10003FD6C: boost::(anonymous namespace)::thread_proxy(void*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x1005A32FB: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 8 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A1618: pthread_key_create (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x10003F9E8: boost::detail::get_current_thread_data() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000139F: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x10004d120 is in the Data segment of /usr/local/lib/libboost_thread.dylib
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during read of size 8 at 0x1005AC448 by thread #2
==79537== Locks held: none
==79537==    at 0x1005A269E: pthread_setspecific (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A32FB: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 8 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A1614: pthread_key_create (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x10003F9E8: boost::detail::get_current_thread_data() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000139F: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x1005ac448 is in the Data segment of /usr/lib/system/libsystem_pthread.dylib
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during write of size 1 at 0x100009D48 by thread #2
==79537== Locks held: none
==79537==    at 0x100000F49: function() (in Build/Products/Debug/cpprules)
==79537==    by 0x10003FD79: boost::(anonymous namespace)::thread_proxy(void*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x1005A32FB: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous read of size 1 by thread #1
==79537== Locks held: none
==79537==    at 0x10000138D: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x100009d48 is in the Data segment of Build/Products/Debug/cpprules
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during write of size 8 at 0x100009D28 by thread #2
==79537== Locks held: none
==79537==    at 0x1005A4099: _pthread_cond_updateval (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A294D: _pthread_cond_signal (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x100000F77: function() (in Build/Products/Debug/cpprules)
==79537==    by 0x10003FD79: boost::(anonymous namespace)::thread_proxy(void*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x1005A32FB: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 8 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A3DE1: _pthread_cond_wait (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1000014AA: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x100009d28 is in the Data segment of Build/Products/Debug/cpprules
==79537== 
==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during read of size 8 at 0x1005AC448 by thread #2
==79537== Locks held: none
==79537==    at 0x1005A4791: _pthread_tsd_cleanup (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A44E4: _pthread_exit (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3306: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537== 
==79537== This conflicts with a previous write of size 8 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A1614: pthread_key_create (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x10003F9E8: boost::detail::get_current_thread_data() (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x10000139F: main (in Build/Products/Debug/cpprules)
==79537==  Address 0x1005ac448 is in the Data segment of /usr/lib/system/libsystem_pthread.dylib
==79537== 

...

==79537== ----------------------------------------------------------------
==79537== 
==79537== Possible data race during write of size 8 at 0x100009C98 by thread #1
==79537== Locks held: none
==79537==    at 0x1005A37DD: pthread_mutex_destroy (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x100005D50: boost::mutex::~mutex() (in Build/Products/Debug/cpprules)
==79537==    by 0x1003A38EC: __cxa_finalize_ranges (in /usr/lib/system/libsystem_c.dylib)
==79537==    by 0x1003A3BEF: exit (in /usr/lib/system/libsystem_c.dylib)
==79537==    by 0x1002F05CF: start (in /usr/lib/system/libdyld.dylib)
==79537== 
==79537== This conflicts with a previous read of size 8 by thread #2
==79537== Locks held: none
==79537==    at 0x1005A1655: _pthread_mutex_lock (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x100000EBB: function() (in Build/Products/Debug/cpprules)
==79537==    by 0x10003FD79: boost::(anonymous namespace)::thread_proxy(void*) (in /usr/local/lib/libboost_thread.dylib)
==79537==    by 0x1005A32FB: _pthread_body (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A3278: _pthread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==    by 0x1005A14B0: thread_start (in /usr/lib/system/libsystem_pthread.dylib)
==79537==  Address 0x100009c98 is in the Data segment of Build/Products/Debug/cpprules
==79537== 
==79537== 
==79537== For counts of detected and suppressed errors, rerun with: -v
==79537== Use --history-level=approx or =none to gain increased speed, at
==79537== the cost of reduced accuracy of conflicting-access information
==79537== ERROR SUMMARY: 34 errors from 33 contexts (suppressed: 0 from 0)

关于c++ - boost::thread 应用程序,奇怪的数据竞争报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27537183/

相关文章:

c - 读取大小无效 - 查找命令行平均值

使用 pin、perf 和 valgrind 计算二进制文件执行的指令数

c - Valgrind 消息 : invalid file descriptor 1024 in syscall close()

c++ - 来自类模板的方法模板的完全特化

C++ 将具有非常相关数据的类 Tree 拆分为两个类

c++ - 将 opencv 2.4.6 与 Qt 库链接

multithreading - OS X 有哪些类型的线程?

并发访问且不受数据结构的影响

c++ - 带有 MinGW GCC 的 Eclipse CDT 出现错误 127

java - 如何正确管理单线程执行?