我有以下代码:
std::thread thread;
EventReceiver target;
{
thread = std::thread([&]() {
auto event = new MyEvent();
QCoreApplication::postEvent(&target, event);
}
});
IdleProcessor::processEvents();
thread.join();
}
在哪里
class MyEvent : public QEvent, public async::ExecutorEventInterface
{
public:
MyEvent()
: QEvent(QEvent::User){
};
void execute() override
{
}
};
class EventReceiver : public QObject
{
Q_OBJECT
public:
EventReceiver();
/**
* @brief receives the MainExecutor posted event
* @param event
* @return
*/
bool event(QEvent* event) override
{
auto myEvent = dynamic_cast<ExecutorEventInterface*>(event);
if (myEvent)
{
myEvent->execute();
return true;
}
return false;
}
};
我得到了线程消毒剂报告,但不知道为什么。
==================
WARNING: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call) (pid=56278)
Read of size 8 at 0x7b0800026018 by main thread:
#0 async::EventReceiver::event(QEvent*) eventreceiver.cpp:16 (unittests:x86_64+0x107353775)
#1 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) <null> (QtCore:x86_64+0x1ea917)
#2 AsyncTest_test_Test::TestBody() async_tests.cpp:103 (unittests:x86_64+0x1004fa8f3)
#3 void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) <null> (unittests:x86_64+0x1042addbd)
#4 TestApplication::event(QEvent*) testapplication.cpp:20 (unittests:x86_64+0x1041f89cf)
#5 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) <null> (QtCore:x86_64+0x1ea917)
#6 start <null> (libdyld.dylib:x86_64+0x163d4)
Previous write of size 8 at 0x7b0800026018 by thread T4:
#0 async::ExecutorEventInterface::ExecutorEventInterface() executoreventinterface.h:9 (unittests:x86_64+0x10058dd10)
#1 MyEvent::MyEvent() async_tests.cpp:73 (unittests:x86_64+0x100599466)
#2 MyEvent::MyEvent() async_tests.cpp:74 (unittests:x86_64+0x1005993e8)
#3 AsyncTest_test_Test::TestBody()::$_6::operator()() const async_tests.cpp:98 (unittests:x86_64+0x100599322)
#4 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, AsyncTest_test_Test::TestBody()::$_6> >(void*) type_traits:4428 (unittests:x86_64+0x100598fb5)
Location is heap block of size 32 at 0x7b0800026000 allocated by thread T4:
#0 operator new(unsigned long) <null> (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6d723)
#1 AsyncTest_test_Test::TestBody()::$_6::operator()() const async_tests.cpp:98 (unittests:x86_64+0x100599308)
#2 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, AsyncTest_test_Test::TestBody()::$_6> >(void*) type_traits:4428 (unittests:x86_64+0x100598fb5)
Thread T4 (tid=424005, finished) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x2936d)
#1 std::__1::thread::thread<AsyncTest_test_Test::TestBody()::$_6, void>(AsyncTest_test_Test::TestBody()::$_6&&) __threading_support:336 (unittests:x86_64+0x100598642)
#2 std::__1::thread::thread<AsyncTest_test_Test::TestBody()::$_6, void>(AsyncTest_test_Test::TestBody()::$_6&&) thread:360 (unittests:x86_64+0x1004faa88)
#3 AsyncTest_test_Test::TestBody() async_tests.cpp:94 (unittests:x86_64+0x1004fa81e)
#4 void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) <null> (unittests:x86_64+0x1042addbd)
#5 TestApplication::event(QEvent*) testapplication.cpp:20 (unittests:x86_64+0x1041f89cf)
#6 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) <null> (QtCore:x86_64+0x1ea917)
#7 start <null> (libdyld.dylib:x86_64+0x163d4)
SUMMARY: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call) eventreceiver.cpp:16 in async::EventReceiver::event(QEvent*)
考虑到 EventReceiver 是在线程中创建并发布到主线程,为什么会发生这种情况,这似乎是虚拟方法执行的竞争,但此时对象已完全构造。
后期编辑 虽然这似乎是一场良性的比赛。消毒剂不知道/看到 EventReceiver::event(QEvent* event) 在使用 QCoreApplication::postEvent(&target, event) 之后发生/由使用 QCoreApplication::postEvent(&target, event) 引起,这发生在 MyEvent 构造之后(因为 MyEvent 实例输入到 QCoreApplication::事后)
我可以添加明确的围栏以使消毒剂清楚这一点,但这似乎过分了?想知道是否建议只使用一些注释来禁用它。