Слоты Qt не вызываются в режиме выпуска, и я виню QSharedPointer

У меня проблема с механизмом сигнальных слотов, возможно, это проблема с QSharedPointer, так как умные указатели для меня новы.

Небольшое пояснение контекста: TCPAssociation является дочерним классом LANAssociation. TCPClient является дочерним классом для LANClient. LANClient имеет защищенную QSharedPointer<LANAssociation> connection переменную, TCPClient имеет приватную QSharedPointer<TCPAssociation> conn; оба указывают на один и тот же объект, созданный в переопределенной чистой виртуальной функции, показанной ниже:

void TCPClient::startNewConnection(const QHostAddress &address)
{
    conn.clear();
    connection.clear();

    conn = QSharedPointer<TCPAssociation>(new TCPAssociation(address, port, QString("Client %1").arg(hostId())));
    Q_ASSERT(conn);

    Q_ASSERT(connect(conn.data(), &LANAssociation::started, this, &LANClient::assoc_started, Qt::UniqueConnection));

    connection = conn.staticCast<LANAssociation>();
    Q_ASSERT(connection);
    conn->start();
    //TCPAssociation::start() { doStuff(); emit started(); }
}

Код отлично работает в Windows 10 в режиме отладки. В режиме выпуска в Linux LANClient::assoc_started никогда не вызывается.

Теперь я запустил свое серверное приложение (вышеупомянутая функция из клиентского приложения) в выпуске в Windows, и я вижу, что еще один слот не вызывается в выпуске, но отлично работает в отладке:

void ThreadController::init(ThreadWorker *worker)
{
    worker->moveToThread(&workerThread);

    Q_ASSERT(connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater, Qt::UniqueConnection));
    Q_ASSERT(connect(this, &ThreadController::operate, worker, &ThreadWorker::doWork, Qt::UniqueConnection));
    Q_ASSERT(connect(worker, &ThreadWorker::finished, this, &ThreadController::finished, Qt::BlockingQueuedConnection));
    doConnects(worker);

    workerThread.start();
}

*worker указывает на дочерний класс ThreadWorker. ThreadWorker::doWork() — виртуальная функция. Это было вызвано в отладке, а не в выпуске. Я исправил это, сделав doWork() чисто виртуальным - теперь он вызывается и в отладке, и в релизе.

У меня также проблема с объектами QTcpSocket и QUdpSocket, которые не излучают connected() или readyRead(). Теперь я понимаю, что это, вероятно, потому, что я использую QSharedPointer<QAbstractSocket> для управления ими, но:

  1. почему разница между отладкой и выпуском? как это сделать правильно?

  2. Должен ли я прекратить использовать наследование или общие указатели?

  3. почему TCPAssociation::started() не испускается? LANClient::assoc_started также не является виртуальной функцией.

person smsware    schedule 28.02.2020    source источник
comment
Я думаю, вы можете попробовать вызвать метод подключения вне макроса Q_ASSERT. В зависимости от конфигурации он может никогда не вызываться.   -  person Fabio    schedule 28.02.2020


Ответы (1)


Выражение внутри макроса Q_ASSERT не будет оцениваться в конфигурациях сборки без отладки:

Q_ASSERT() полезен для тестирования предварительных и конечных условий во время разработки. Он ничего не делает, если QT_NO_DEBUG был определен во время компиляции.

https://doc.qt.io/qt-5/qtglobal.html#Q_ASSERT

person Vladimir Bershov    schedule 28.02.2020