调试boost::thread应用,误报率高
我编写了一个 boost::thread 应用程序,其中可能有一些竞争条件。我想调试这个程序。因此我使用了以下 valgrind 工具:
- halgrind
- drd
不幸的是它们的误报率非常高。因此,使用下面的非常简单的程序 valgrind --tool=drd
会抱怨 94 个错误,而实际上不应该有。因此,在我的复杂程序中,我遇到了大约 15000 个错误。所以很难找到真正的错误。
我可以使用以下 boost 库 1.46.0 和 1.47.0 重现此行为。并使用 valgrind 3.7.0 SVN 和 valgrind 3.8.0 SVN。我尝试过的操作系统是 Ubuntu 11.10 和 Mac OS X 10.7。其中编译器为gcc 4.2.1和gcc 4.6.1。
#include <iostream>
#include <boost/thread.hpp>
void run()
{
//do some stuff here
}
int main(int argc, char* argv[])
{
boost::thread thread(run);
thread.join();
std::cerr << "main: done" << std::endl;
return 0;
}
;
如何调试 boost 线程程序?还有其他更适合的工具吗?
解决方案
3.6.1版本之后的valgrind似乎被破坏了。如果我使用 valgrind 3.6.1 一切正常。
这是来自 valgrind --tool=drd
的错误报告:
==60767== Thread 1:
==60767== Conflicting store by thread 1 at 0x100026ec0 size 8
==60767== at 0x2A316E: pthread_mutex_lock (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A82FA: _pthread_cond_wait (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x32A4E: boost::condition_variable::wait(boost::unique_lock<boost::mutex>&) (in /usr/local/lib/libboost_thread.dylib)
==60767== by 0x2BE5A: boost::thread::join() (in /usr/local/lib/libboost_thread.dylib)
==60767== by 0x10000195C: main (in ./playgroudThreads)
==60767== Address 0x100026ec0 is at offset 144 from 0x100026e30. Allocation context:
==60767== at 0xC5B3: malloc (vg_replace_malloc.c:266)
==60767== by 0x9968D: operator new(unsigned long) (in /usr/lib/libstdc++.6.0.9.dylib)
==60767== by 0x1000069ED: boost::detail::thread_data<void (*)()>* boost::detail::heap_new_impl<boost::detail::thread_data<void (*)()>, void (*&)()>(void (*&)()) (in ./playgroudThreads)
==60767== by 0x100006A87: boost::detail::thread_data<void (*)()>* boost::detail::heap_new<boost::detail::thread_data<void (*)()>, void (*)()>(void (*&)()) (in ./playgroudThreads)
==60767== by 0x100006ACA: boost::shared_ptr<boost::detail::thread_data_base> boost::thread::make_thread_info<void (*)()>(void (*)()) (in ./playgroudThreads)
==60767== by 0x100006B08: boost::thread::thread<void (*)()>(void (*)(), boost::disable_if<boost::is_convertible<void (*&)(), boost::detail::thread_move_t<void (*)()> >, boost::thread::dummy*>::type) (in ./playgroudThreads)
==60767== by 0x100001950: main (in ./playgroudThreads)
==60767== Other segment start (thread 2)
==60767== at 0x2A7B68: thread_start (in /usr/lib/system/libsystem_c.dylib)
==60767== Other segment end (thread 2)
==60767== at 0x3E667A: mach_msg_trap (in /usr/lib/system/libsystem_kernel.dylib)
==60767== by 0x3DED38: semaphore_create (in /usr/lib/system/libsystem_kernel.dylib)
==60767== by 0x2A50F7: new_sem_from_pool (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A6199: _pthread_exit (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A48C9: _pthread_start (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A7B74: thread_start (in /usr/lib/system/libsystem_c.dylib)
I have programmed a boost::thread application, where I might have some race conditions. I want to debug this program. Therefore I used the following valgrind tools:
- halgrind
- drd
unfortunately they have a very false positive rate. So with the really simple program below valgrind --tool=drd
complains about 94 errors, where no should be. So with my complex program I get about 15000 errors. So it is really hard to find the actual error.
I could reproduce this behavior with the following boost libraries 1.46.0 and 1.47.0. And with valgrind 3.7.0 SVN and valgrind 3.8.0 SVN. The operating systems I tried it out where Ubuntu 11.10 and Mac OS X 10.7. The compiler where gcc 4.2.1 and gcc 4.6.1.
#include <iostream>
#include <boost/thread.hpp>
void run()
{
//do some stuff here
}
int main(int argc, char* argv[])
{
boost::thread thread(run);
thread.join();
std::cerr << "main: done" << std::endl;
return 0;
}
;
How do you debug your boost thread programs? Are there other tools which might be better suited?
Solution
It seems that valgrind after version 3.6.1 is broken. If I use valgrind 3.6.1 everything works fine.
Here on error report from valgrind --tool=drd
:
==60767== Thread 1:
==60767== Conflicting store by thread 1 at 0x100026ec0 size 8
==60767== at 0x2A316E: pthread_mutex_lock (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A82FA: _pthread_cond_wait (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x32A4E: boost::condition_variable::wait(boost::unique_lock<boost::mutex>&) (in /usr/local/lib/libboost_thread.dylib)
==60767== by 0x2BE5A: boost::thread::join() (in /usr/local/lib/libboost_thread.dylib)
==60767== by 0x10000195C: main (in ./playgroudThreads)
==60767== Address 0x100026ec0 is at offset 144 from 0x100026e30. Allocation context:
==60767== at 0xC5B3: malloc (vg_replace_malloc.c:266)
==60767== by 0x9968D: operator new(unsigned long) (in /usr/lib/libstdc++.6.0.9.dylib)
==60767== by 0x1000069ED: boost::detail::thread_data<void (*)()>* boost::detail::heap_new_impl<boost::detail::thread_data<void (*)()>, void (*&)()>(void (*&)()) (in ./playgroudThreads)
==60767== by 0x100006A87: boost::detail::thread_data<void (*)()>* boost::detail::heap_new<boost::detail::thread_data<void (*)()>, void (*)()>(void (*&)()) (in ./playgroudThreads)
==60767== by 0x100006ACA: boost::shared_ptr<boost::detail::thread_data_base> boost::thread::make_thread_info<void (*)()>(void (*)()) (in ./playgroudThreads)
==60767== by 0x100006B08: boost::thread::thread<void (*)()>(void (*)(), boost::disable_if<boost::is_convertible<void (*&)(), boost::detail::thread_move_t<void (*)()> >, boost::thread::dummy*>::type) (in ./playgroudThreads)
==60767== by 0x100001950: main (in ./playgroudThreads)
==60767== Other segment start (thread 2)
==60767== at 0x2A7B68: thread_start (in /usr/lib/system/libsystem_c.dylib)
==60767== Other segment end (thread 2)
==60767== at 0x3E667A: mach_msg_trap (in /usr/lib/system/libsystem_kernel.dylib)
==60767== by 0x3DED38: semaphore_create (in /usr/lib/system/libsystem_kernel.dylib)
==60767== by 0x2A50F7: new_sem_from_pool (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A6199: _pthread_exit (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A48C9: _pthread_start (in /usr/lib/system/libsystem_c.dylib)
==60767== by 0x2A7B74: thread_start (in /usr/lib/system/libsystem_c.dylib)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自 DRD 手册
因此,如果实现仅使用 POSIX 线程而不是 Linux 的 futex 等非 POSIX 内容,则 DRD 不会出现任何误报。
因此,如果 DRD 在像您这样的无竞争程序上报告误报,则它存在错误。它不应该有误报。
但是,我无法在我的机器上重现您报告的错误(Archlinux/ gcc 4.6.2 / valgrind 3.6.1 / boost 1.47)。
From DRD manual
So DRD does not have any false positive if the implementation uses just POSIX threads and not non-POSIX stuff like Linux's futex.
Therefore, if DRD reports a false positive, on a race-free program like yours, it has a bug. It is not supposed to have false positives.
However, I could not reproduce the errors you reported, on my machine (Archlinux/ gcc 4.6.2 / valgrind 3.6.1 / boost 1.47).