У меня следующий код:
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), что происходит после создания MyEvent (поскольку экземпляр MyEvent вводится в QCoreApplication :: postEvent)
Я могу добавить явное ограждение для того, чтобы это было ясно для дезинфицирующего средства, но это кажется чрезмерным? Интересно, рекомендуется ли использовать некоторые аннотации, чтобы отключить это?