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();
    }
    
    

  • Lifetime Qt Champion

    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?


  • Lifetime Qt Champion

    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").
    Calling deleteLater() after the thread event loop finished is a memory leak however





  • 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.