- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
有一个类只有一个信号槽:
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
#include <QObject>
class SomeClass : public QObject
{
Q_OBJECT
public:
explicit SomeClass(QObject *parent = 0) : QObject(parent) {
connect(this, &SomeClass::valueChanged, this, &SomeClass::setValue);
}
void emitSignal() {
emit valueChanged();
}
signals:
void valueChanged();
public slots:
void setValue() {}
};
#endif // SOME_CLASS_H
这是定义单例的程序的主文件,它创建上面定义的类的实例并将其放入单独的线程中:
#include <QCoreApplication>
#include <QThread>
#include <someclass.h>
class Singleton {
public:
QThread t;
SomeClass someClassObject;
Singleton() {
someClassObject.moveToThread(&t);
t.start();
}
static SomeClass& getInstance() {
static Singleton st;
return st.someClassObject;
}
~Singleton() {
t.quit();
t.wait();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
SomeClass& b = Singleton::getInstance();
b.emitSignal();
QThread::msleep(100);
return a.exec();
}
问题是,当我使用一些线程检查工具(如 ThreadSanitizer 或 Helgrind)评估此程序时,会报告几个关于数据竞争条件的警告。 ThreadSanitizer 的示例输出:
==================
WARNING: ThreadSanitizer: data race (pid=3827)
Read of size 8 at 0x7d040000f6a0 by thread T1:
#0 void QtPrivate::FunctionPointer<void (SomeClass::*)()>::call<void, void>(void (SomeClass::*)(), SomeClass*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:142 (exe+0x0000000a2d1c)
#1 QtPrivate::QSlotObject<void (SomeClass::*)(), void, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobject_impl.h:149 (exe+0x0000000a29b4)
#2 QObject::event(QEvent*) ??:0 (libQt5Core.so.5+0x00000029022d)
Previous write of size 8 at 0x7d040000f6a0 by main thread:
#0 malloc ??:0 (exe+0x0000000426e9)
#1 QMetaObject::activate(QObject*, int, int, void**) ??:0 (libQt5Core.so.5+0x00000028ef1c)
#2 main /tmp/project/main.cpp:31 (exe+0x0000000a19f2)
Location is heap block of size 8 at 0x7d040000f6a0 allocated by main thread:
#0 malloc ??:0 (exe+0x0000000426e9)
#1 QMetaObject::activate(QObject*, int, int, void**) ??:0 (libQt5Core.so.5+0x00000028ef1c)
#2 main /tmp/project/main.cpp:31 (exe+0x0000000a19f2)
Thread T1 'QThread' (tid=3829, running) created by main thread at:
#0 pthread_create ??:0 (exe+0x000000046f6b)
#1 QThread::start(QThread::Priority) ??:0 (libQt5Core.so.5+0x0000000928b7)
#2 Singleton::getInstance() /tmp/project/main.cpp:16 (exe+0x0000000a1b3c)
#3 main /tmp/project/main.cpp:30 (exe+0x0000000a19bf)
SUMMARY: ThreadSanitizer: data race /usr/include/qt5/QtCore/qobjectdefs_impl.h:142 void QtPrivate::FunctionPointer<void (SomeClass::*)()>::call<void, void>(void (SomeClass::*)(), SomeClass*, void**)
==================
==================
WARNING: ThreadSanitizer: data race (pid=3827)
Write of size 1 at 0x7d040000f6b0 by thread T1:
#0 free ??:0 (exe+0x000000042dfb)
#1 QMetaCallEvent::~QMetaCallEvent() ??:0 (libQt5Core.so.5+0x00000028d3a4)
Previous write of size 8 at 0x7d040000f6b0 by main thread:
#0 malloc ??:0 (exe+0x0000000426e9)
#1 QMetaObject::activate(QObject*, int, int, void**) ??:0 (libQt5Core.so.5+0x00000028eefe)
#2 main /tmp/project/main.cpp:31 (exe+0x0000000a19f2)
Location is heap block of size 4 at 0x7d040000f6b0 allocated by main thread:
#0 malloc ??:0 (exe+0x0000000426e9)
#1 QMetaObject::activate(QObject*, int, int, void**) ??:0 (libQt5Core.so.5+0x00000028eefe)
#2 main /tmp/project/main.cpp:31 (exe+0x0000000a19f2)
Thread T1 'QThread' (tid=3829, running) created by main thread at:
#0 pthread_create ??:0 (exe+0x000000046f6b)
#1 QThread::start(QThread::Priority) ??:0 (libQt5Core.so.5+0x0000000928b7)
#2 Singleton::getInstance() /tmp/project/main.cpp:16 (exe+0x0000000a1b3c)
#3 main /tmp/project/main.cpp:30 (exe+0x0000000a19bf)
SUMMARY: ThreadSanitizer: data race ??:0 free
==================
==================
WARNING: ThreadSanitizer: data race (pid=3827)
Write of size 8 at 0x7d180000edc0 by thread T1:
#0 operator delete(void*) ??:0 (exe+0x00000004392b)
#1 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ??:0 (libQt5Core.so.5+0x000000269e0f)
Previous write of size 8 at 0x7d180000edc0 by main thread:
#0 operator new(unsigned long) ??:0 (exe+0x0000000432b9)
#1 QMetaObject::activate(QObject*, int, int, void**) ??:0 (libQt5Core.so.5+0x00000028ef94)
#2 main /tmp/project/main.cpp:31 (exe+0x0000000a19f2)
Location is heap block of size 88 at 0x7d180000edc0 allocated by main thread:
#0 operator new(unsigned long) ??:0 (exe+0x0000000432b9)
#1 QMetaObject::activate(QObject*, int, int, void**) ??:0 (libQt5Core.so.5+0x00000028ef94)
#2 main /tmp/project/main.cpp:31 (exe+0x0000000a19f2)
Thread T1 'QThread' (tid=3829, running) created by main thread at:
#0 pthread_create ??:0 (exe+0x000000046f6b)
#1 QThread::start(QThread::Priority) ??:0 (libQt5Core.so.5+0x0000000928b7)
#2 Singleton::getInstance() /tmp/project/main.cpp:16 (exe+0x0000000a1b3c)
#3 main /tmp/project/main.cpp:30 (exe+0x0000000a19bf)
SUMMARY: ThreadSanitizer: data race ??:0 operator delete(void*)
==================
是什么导致了这些竞争条件?
最佳答案
由于警告都源自与信号、槽和事件循环相关的 Qt 内部,我认为检测到的竞争条件是误报。 Helgrind 是否检测到相同的竞争条件?一些人 ( http://www.kdab.com/~dfaure/helgrind.html ) 报告了 Qt 的 Helgrind 错误,并且最近似乎已得到解决。
关于c++ - Qt moveToThread 和数据竞争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25460994/
将对象从一个线程移动到另一个线程时,moveToThread()自动将现有的直接连接重写为排队的连接? 或者换句话说:在调用 moveToThread() 之前或之后建立自动连接是否重要? ? 不幸的
我有以下类(class): class commMonitor : QObject { Q_OBJECT public: commMonitor(); ~commMonitor
是否可以将成员函数移动到新线程而不是整个类? 将其置于上下文中: class FooBar : public QObject { Q_OBJECT // some other
如果类型为 QObject 的对象被移动到一个线程 QObject::moveToThread ,对象接收到的所有信号都在该线程内处理。但是,如果直接调用插槽( object->theSlot() )
我有这样一个类: class myClass:public QThread 然后在它的构造函数中我做了: myClass::myClass(){ moveToThread(this);
我有一个类 Manager class Manager : public QThread { Q_OBJECT public: Manager(); void run(
我有一个用于 GUI 的主线程,其中运行 MainWindow 对象,在它的构造函数中,我创建了一个新的 worker 对象和一个 QThread 对象,然后我将 worker 移动到线程,问题是当打
在 QThread class 的文档中一个示例性设置的工作原理如下: public: Controller() { Worker *worker = new Worker; work
有一个类只有一个信号槽: #ifndef SOME_CLASS_H #define SOME_CLASS_H #include class SomeClass : public QObject {
我的IDE Qt 5.0.1,平台Linux 我对将小部件设置为窗口有疑问。(我的意见) 这是我的 main.cpp-> int main(int argc, char *argv[]) {
我搜索了这个站点和 QT 文档,但找不到以下问题的直接答案: 假设我有一个只有一个插槽的 worker 类: void Worker::testSlot(){ //access data and
我在 python 中使用 opencv2 和代码 import cv2 cv2.namedWindow("output", cv2.WINDOW_NORMAL) cv2.imshow("
我正在尝试使用线程创建程序:主要从一个循环开始。当测试返回 true 时,我创建一个对象并希望该对象在另一个线程中工作然后返回并开始测试。 QCoreApplication a(argc, argv)
我尝试使用来自 https://wiki.qt.io/QThreads_general_usage 的方法与 moveToThread。一切安好。但是,如果我尝试将参数添加到完成的信号中,则会出现以下
我有这样的东西: main.cpp int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); static
我刚刚开始在 Windows 上使用 Qt 并阅读了有关 moveToThread() 函数的信息。如果我这样写可以吗: class Worker : public QObject { Q_O
我试图在 Qt 中使用线程将一些工作委托(delegate)给线程,但我无法让它工作。我有一个继承 QMainWindow 的类,它有一个启动线程来工作的成员对象。该对象以 QMainwindow 作
我们什么时候在线程应用程序中使用每个函数调用。给定在同一个类中定义的两个函数 fun1() 和 fun2() 处理将数据读/写到缓冲区(队列操作)。实现多线程就这些。我们将不得不在单独的线程中运行这两
我刚开始使用多线程,在将对象移动到 QThread 时遇到了一些麻烦。我的 Controller 类实例化了 Worker,为 Worker 创建了必要的线程并将 Worker 移动到新线程。当工作线
我正在构建一个小型多线程 Web 服务器。 QTcpSockets 在主线程中获取,然后由 QtConcurrent 移交给 QThreadPool,后者最终处理数据并发出答案。 我的问题是套接字是在
我是一名优秀的程序员,十分优秀!