Qt 插槽在发布模式下不被调用,我责怪 QSharedPointer
Qt slots are not called in release mode and I blame QSharedPointer
我对 signal-slot 机制有疑问,可能实际上是 QSharedPointer
的问题,因为智能指针对我来说是新的。
上下文的一点解释:
TCPAssociation
是 LANAssociation
的 child class。 TCPClient
是 child class 到 LANClient
。 LANClient
保护了QSharedPointer<LANAssociation> connection
变量,TCPClient
保护了QSharedPointer<TCPAssociation> conn
;两者都指向相同的 object 正在重写的纯虚函数中创建,如下所示:
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
的 child class。 ThreadWorker::doWork()
是虚函数。它是在调试中调用的,而不是在发布中。我通过制作 doWork()
纯虚拟来修复它 - 现在它在调试和发布中都被调用。
我还遇到 QTcpSocket
和 QUdpSocket
object 不发出 connected()
或 readyRead()
的问题。现在我明白了,这可能是因为我正在使用 QSharedPointer<QAbstractSocket>
来管理它们,但是:
为什么debug和release有区别?如何正确操作?
我应该停止使用继承或共享指针吗?
- 为什么
TCPAssociation::started()
没有被发射? LANClient::assoc_started
也不是虚函数。
Q_ASSERT
宏中的表达式将不会在非调试构建配置中计算:
Q_ASSERT()
is useful for testing pre- and post-conditions during
development. It does nothing if QT_NO_DEBUG
was defined during
compilation.
我对 signal-slot 机制有疑问,可能实际上是 QSharedPointer
的问题,因为智能指针对我来说是新的。
上下文的一点解释:
TCPAssociation
是 LANAssociation
的 child class。 TCPClient
是 child class 到 LANClient
。 LANClient
保护了QSharedPointer<LANAssociation> connection
变量,TCPClient
保护了QSharedPointer<TCPAssociation> conn
;两者都指向相同的 object 正在重写的纯虚函数中创建,如下所示:
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
的 child class。 ThreadWorker::doWork()
是虚函数。它是在调试中调用的,而不是在发布中。我通过制作 doWork()
纯虚拟来修复它 - 现在它在调试和发布中都被调用。
我还遇到 QTcpSocket
和 QUdpSocket
object 不发出 connected()
或 readyRead()
的问题。现在我明白了,这可能是因为我正在使用 QSharedPointer<QAbstractSocket>
来管理它们,但是:
为什么debug和release有区别?如何正确操作?
我应该停止使用继承或共享指针吗?
- 为什么
TCPAssociation::started()
没有被发射?LANClient::assoc_started
也不是虚函数。
Q_ASSERT
宏中的表达式将不会在非调试构建配置中计算:
Q_ASSERT()
is useful for testing pre- and post-conditions during development. It does nothing ifQT_NO_DEBUG
was defined during compilation.