2

我有以下代码:

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::事后)

我可以添加明确的围栏以使消毒剂清楚这一点,但这似乎过分了?想知道是否建议只使用一些注释来禁用它。

4

0 回答 0