Solved Exception after deletion QTcpSocket
-
Hi,
I wrote a simple Server class that accepts the first connection request, but rejects other. When the first connection is disconnected, the server can again accept the first another connection request.
I wrote a simple code to test the Server class. This code sets up connection to the Server, then it disconnects from and then reconnects to the Server.
But when I run Server application and test application I get an exception on the "a.exec();" line of main.cpp file of the Server application.
I suspect that it is somehow related with socket deletion, because when I remove the "delete m_socket;" line in the server.cpp this exception disappears.
What have I done wrong?main.cpp of Server application #include <QCoreApplication> #include "server.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Server server; server.listen(QHostAddress::Any, 47326); return a.exec(); }
server.h #ifndef SERVER_H #define SERVER_H #include <QTcpServer> #include <QTcpSocket> class Server : public QObject { Q_OBJECT public: explicit Server(QObject *parent = nullptr); void listen(QHostAddress hostAddress, quint16 port); public slots: void handleConnectionRequest(); void handleSocketDisconnetion(); private: QTcpServer *m_server; QTcpSocket *m_socket = nullptr; }; #endif // SERVER_H
server.cpp #include "server.h" Server::Server(QObject *parent) : QObject(parent), m_server(new QTcpServer(this)) { connect(m_server, &QTcpServer::newConnection, this, &Server::handleConnectionRequest); } void Server::listen(QHostAddress hostAddress, quint16 port) { m_server->listen(hostAddress, port); } void Server::handleConnectionRequest() { QTcpSocket *socket = m_server->nextPendingConnection(); qInfo() << "New connection request entered"; if (m_socket == nullptr) { m_socket = socket; connect(socket, &QTcpSocket::disconnected, this, &Server::handleSocketDisconnetion); qInfo() << "The connection request is accepted"; } else { delete socket; qInfo() << "The connection request is rejected"; } } void Server::handleSocketDisconnetion() { delete m_socket; m_socket = nullptr; qInfo() << "Socket is deleted"; }
main.cpp of test application #include <QCoreApplication> #include <QTcpSocket> #include <QHostAddress> #include <QThread> void connect(QTcpSocket &socket) { socket.connectToHost(QHostAddress("127.0.0.1"), 47326); if (socket.waitForConnected(-1)) qInfo() << "Connected"; else qInfo() << socket.errorString(); QThread::msleep(100); } void disconnect(QTcpSocket &socket) { socket.disconnectFromHost(); if (socket.state() == QAbstractSocket::UnconnectedState || socket.waitForDisconnected(-1)) qInfo() << "Disconnected"; else qInfo() << socket.errorString(); QThread::msleep(100); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpSocket socket; connect(socket); disconnect(socket); connect(socket); return a.exec(); }
-
Hi and welcome to devnet,
You should rather use
socker->deleteLater();
. That will allow the event loop to handle pending actions on the socket. -
@SGaist Thank you, deleteLater () eliminates the exception.
Could you give advice when should I use deleteLater() to delete a QObject? -
Each time you want to delete a connected QObject.
-
@SGaist said in Exception after deletion QTcpSocket:
connected QObject.
Specifically, a QObject connected on the receiving end (i.e. the QObject you are deleting might be called "as a slot").
CallingdeleteLater()
after the thread event loop finished is a memory leak however -
Probably I have found answers about using deleteLater().
https://stackoverflow.com/a/4889395
http://doc.qt.io/qt-5/qobject.html#deleteLater
http://doc.qt.io/qt-5/qobject.html#dtor.QObject -
To cover 90% of use cases:
if you are in the main thread and you use the classic main:int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); //something return a.exec(); }
then always use
deleteLater()
as it's 100% safe.