QThread:用最简单的代码竞态条件
QThread: race condition with the simplest code
调试我正在工作的应用程序,我发现了一些奇怪的竞争条件显然不是由我们的代码引起的。Helgrind在几秒钟内报告了5000多个潜在的竞争条件。
代码如下:
#include <QApplication>
#include <QThread>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QThread thread;
thread.start();
return app.exec();
}
下面是hellgrind报告的开头部分:
==9856== Helgrind, a thread error detector
==9856== Copyright (C) 2007-2015, and GNU GPL'd, by OpenWorks LLP et al.
==9856== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9856== Command: /home/gianks/NetBeansProjects/ThreadTest/dist/Debug/GNU-Linux/ThreadTest
==9856==
==9856== ---Thread-Announcement------------------------------------------
==9856==
==9856== Thread #1 is the program's root thread
==9856==
==9856== ---Thread-Announcement------------------------------------------
==9856==
==9856== Thread #2 was created
==9856== at 0x6041B1E: clone (clone.S:74)
==9856== by 0x6852189: create_thread (createthread.c:102)
==9856== by 0x6853EC3: pthread_create@@GLIBC_2.2.5 (pthread_create.c:679)
==9856== by 0x4C34BB7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5571DB7: QThread::start(QThread::Priority) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x40F9778: ??? (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40FF5E3: QXcbConnection::QXcbConnection(QXcbNativeInterface*, bool, unsigned int, char const*) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x41029EC: QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40293AC: ??? (in /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so)
==9856== by 0x63E3DD1: QPlatformIntegrationFactory::create(QString const&, QStringList const&, int&, char**, QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0003: QGuiApplicationPrivate::createPlatformIntegration() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0F0C: QGuiApplicationPrivate::createEventDispatcher() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856==
==9856== ----------------------------------------------------------------
==9856==
==9856== Possible data race during read of size 4 at 0x599E9B0 by thread #1
==9856== Locks held: none
==9856== at 0x556AD30: QBasicMutex::unlockInternal() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C344E7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5571D23: QThread::start(QThread::Priority) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x40F9778: ??? (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40FF5E3: QXcbConnection::QXcbConnection(QXcbNativeInterface*, bool, unsigned int, char const*) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x41029EC: QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40293AC: ??? (in /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so)
==9856== by 0x63E3DD1: QPlatformIntegrationFactory::create(QString const&, QStringList const&, int&, char**, QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0003: QGuiApplicationPrivate::createPlatformIntegration() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0F0C: QGuiApplicationPrivate::createEventDispatcher() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x5757A85: QCoreApplication::init() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x5757AF5: QCoreApplication::QCoreApplication(QCoreApplicationPrivate&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856==
==9856== This conflicts with a previous write of size 4 by thread #2
==9856== Locks held: none
==9856== at 0x556A977: QBasicMutex::lockInternal() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C34377: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5572754: ??? (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C34DB6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x68536F9: start_thread (pthread_create.c:333)
==9856== by 0x6041B5C: clone (clone.S:109)
==9856== Address 0x599e9b0 is in the Data segment of /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1
==9856==
==9856== ----------------------------------------------------------------
==9856==
==9856== Possible data race during write of size 8 at 0xBF41830 by thread #1
==9856== Locks held: none
==9856== at 0x556AD3A: QBasicMutex::unlockInternal() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C344E7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5571D23: QThread::start(QThread::Priority) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x40F9778: ??? (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40FF5E3: QXcbConnection::QXcbConnection(QXcbNativeInterface*, bool, unsigned int, char const*) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x41029EC: QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40293AC: ??? (in /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so)
==9856== by 0x63E3DD1: QPlatformIntegrationFactory::create(QString const&, QStringList const&, int&, char**, QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0003: QGuiApplicationPrivate::createPlatformIntegration() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0F0C: QGuiApplicationPrivate::createEventDispatcher() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x5757A85: QCoreApplication::init() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x5757AF5: QCoreApplication::QCoreApplication(QCoreApplicationPrivate&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856==
==9856== This conflicts with a previous read of size 8 by thread #2
==9856== Locks held: none
==9856== at 0x556A9A5: QMutex::lock() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C34377: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5572754: ??? (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C34DB6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x68536F9: start_thread (pthread_create.c:333)
==9856== by 0x6041B5C: clone (clone.S:109)
==9856== Address 0xbf41830 is 112 bytes inside a block of size 168 alloc'd
==9856== at 0x4C2F50F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x556D793: QThread::QThread(QObject*) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x40F96B2: ??? (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40FF5D4: QXcbConnection::QXcbConnection(QXcbNativeInterface*, bool, unsigned int, char const*) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x41029EC: QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40293AC: ??? (in /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so)
==9856== by 0x63E3DD1: QPlatformIntegrationFactory::create(QString const&, QStringList const&, int&, char**, QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0003: QGuiApplicationPrivate::createPlatformIntegration() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0F0C: QGuiApplicationPrivate::createEventDispatcher() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x5757A85: QCoreApplication::init() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x5757AF5: QCoreApplication::QCoreApplication(QCoreApplicationPrivate&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x63F2D08: QGuiApplication::QGuiApplication(QGuiApplicationPrivate&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== Block was alloc'd by thread #1
==9856==
==9856== ----------------------------------------------------------------
==9856==
==9856== Possible data race during read of size 8 at 0xBF41830 by thread #2
==9856== Locks held: none
==9856== at 0x556A92D: QBasicMutex::lockInternal() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C34377: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5572754: ??? (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C34DB6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x68536F9: start_thread (pthread_create.c:333)
==9856== by 0x6041B5C: clone (clone.S:109)
==9856==
==9856== This conflicts with a previous write of size 8 by thread #1
==9856== Locks held: none
==9856== at 0x556AD3A: QBasicMutex::unlockInternal() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x4C344E7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x5571D23: QThread::start(QThread::Priority) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x40F9778: ??? (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40FF5E3: QXcbConnection::QXcbConnection(QXcbNativeInterface*, bool, unsigned int, char const*) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x41029EC: QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40293AC: ??? (in /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so)
==9856== by 0x63E3DD1: QPlatformIntegrationFactory::create(QString const&, QStringList const&, int&, char**, QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== Address 0xbf41830 is 112 bytes inside a block of size 168 alloc'd
==9856== at 0x4C2F50F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==9856== by 0x556D793: QThread::QThread(QObject*) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x40F96B2: ??? (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40FF5D4: QXcbConnection::QXcbConnection(QXcbNativeInterface*, bool, unsigned int, char const*) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x41029EC: QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**) (in /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.5.1)
==9856== by 0x40293AC: ??? (in /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so)
==9856== by 0x63E3DD1: QPlatformIntegrationFactory::create(QString const&, QStringList const&, int&, char**, QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0003: QGuiApplicationPrivate::createPlatformIntegration() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x63F0F0C: QGuiApplicationPrivate::createEventDispatcher() (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== by 0x5757A85: QCoreApplication::init() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x5757AF5: QCoreApplication::QCoreApplication(QCoreApplicationPrivate&) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1)
==9856== by 0x63F2D08: QGuiApplication::QGuiApplication(QGuiApplicationPrivate&) (in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.5.1)
==9856== Block was alloc'd by thread #1
真的有bug吗?
一个注意:我也试过调用开始与排队连接,相同的效果,所以开始事件循环之前的其他线程不是一个解决方案。
谢谢
helgrind不理解Qt内部使用的原子。您需要抑制该警告(并忽略它)。获取:
https://github.com/KDE/kde-dev-scripts/blob/master/kde.supp并将--suppressions=/path/to/kde.supp
添加到helgrind命令行。
有关在Qt应用程序中使用helgrind的更多信息,请查看这篇博客文章。
(旁注:破坏一个仍在运行的QThread会使你的程序崩溃,所以一定要在从main返回之前加入它)
您没有以正确的方式使用QThread,按照Qt文档http://doc.qt.io/qt-5/qthread.html
您需要创建QThread的子类并重新实现run(),或者您可以使用QObject::moveToThread()将worker对象移动到线程中。
相关文章:
- 给定使用 Bitmask 的解决方案,我无法理解代码中标记的条件评估
- 条件不变的 if 语句会减慢我的C++代码吗?
- 为什么在同一条件变量上使用多个互斥锁会使此代码崩溃?
- C++代码在 for 循环的条件下给出运行时错误,而如果它被具有相同意义的代码替换,则编译正确
- 为什么此代码不创建争用条件?
- 我可以在一行代码中将向量中与条件匹配的所有元素插入到集合中吗?
- C 模板:如何根据数据类型有条件编译不同的代码
- 可视化优雅C++代码:如何使用 while 循环和条件语句编写更高效的代码
- 如何在没有'switch'和'if-else'条件的情况下重写以下代码?
- 当满足条件时,是否可以在 GLSL 着色器中回调 C/C++ 函数/代码
- 为什么跨线程更改共享变量的代码显然没有受到竞争条件的影响
- 如果类型(不)相等,是否可以C++有条件地编译代码?
- c while()..执行代码行的条件
- OSX OpenGL设置代码中的种族条件
- 有条件地定义在运行时,在C 代码的其余部分中将使用3类
- C++模板可以用于条件代码包含吗
- C++模板中条件代码实例化的最干净方法
- c++宏:条件代码包含在表达式NOT语句中
- 在基于文本的冒险游戏中,我该如何避免冗长而令人困惑的条件代码
- 模板函数中的条件代码生成