Russian Qt Forum
Ноябрь 24, 2024, 19:08 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Утечка памяти в многопточном Tcp server  (Прочитано 2804 раз)
akaMDA
Гость
« : Сентябрь 19, 2012, 11:09 »

Примитивный многопоточный Tcp сервер. При новом подключении создается поток для работы с клиентом. При отключении поток уничтожается. Написал клиент который подключается и тут же отваливается и так в цикле. В результате у Tcp сервера растет неограниченно память. И после нескольких минут работы - отказ выделения памяти - буфер переполнен.  ОС - Win7 x64. qt 4.8.1.
Туплю и не могу понять в чем причина. Если не трудно, подскажите. Код ниже.

Код:
main.cpp

#include <QtCore/QCoreApplication>

#include <iostream>

#include <Windows.h>

#include "tcpserver.h"
////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << "START TCP SERVER PID: " << GetCurrentProcessId() << " TID: " << GetCurrentThreadId() << std::endl;

    tcpServer* tcpS = new tcpServer();
    QSharedPointer<tcpServer> ptcpS = QSharedPointer<tcpServer>(tcpS, &QObject::deleteLater);

    if(!tcpS->listen(QHostAddress::Any, 5103))
    {
        std::cout << "Error listen(): " << tcpS->errorString().toStdString().c_str() << std::endl;
    }
   
    return a.exec();
}
////////////////////////////////////////////////////////////////////


tspserver.h

#ifndef TCPSERVER_H
#define TCPSERVER_H
////////////////////////////////////////////////////////////////////
#include <QtCore/QtCore>
#include <QtNetwork/QtNetwork>

#include <iostream>

#include <Windows.h>


#include "tcpclient.h"
////////////////////////////////////////////////////////////////////
class tcpServer : public QTcpServer
{
    Q_OBJECT

    QMap<int, QSharedPointer<tcpClient> > clients;
////////////////////////////////////////////////////////////////////
public:
    explicit tcpServer(QObject *_parent = 0);
////////////////////////////////////////////////////////////////////
protected:
    void incomingConnection(int _socketDescriptor);
////////////////////////////////////////////////////////////////////
signals:
////////////////////////////////////////////////////////////////////
public slots:
////////////////////////////////////////////////////////////////////
private slots:
    void clientDisconnected();
////////////////////////////////////////////////////////////////////
};
#endif // TCPSERVER_H

tspserver.cpp
#include "tcpserver.h"
////////////////////////////////////////////////////////////////////
tcpServer::tcpServer(QObject *_parent) :
    QTcpServer(_parent)
{
}
////////////////////////////////////////////////////////////////////
void tcpServer::incomingConnection(int _socketDescriptor)
{
    std::cout << __FUNCTION__ << " " << GetCurrentThreadId() << " " << _socketDescriptor << std::endl;

    tcpClient* tcpCl = new tcpClient(_socketDescriptor);
    QSharedPointer<tcpClient> ptcpCl = QSharedPointer<tcpClient>(tcpCl, &QObject::deleteLater);

    this->connect(tcpCl, SIGNAL(finished()), this, SLOT(clientDisconnected()));

    this->clients.insert(_socketDescriptor, ptcpCl);

    tcpCl->start();
}
////////////////////////////////////////////////////////////////////
void tcpServer::clientDisconnected()
{
    std::cout << __FUNCTION__ << " " << GetCurrentThreadId() << std::endl;

    tcpClient* tcpCl = qobject_cast<tcpClient*>(sender());

    int key = tcpCl->getSocketDescriptor();

    if(this->clients.contains(key))
    {
        this->clients.remove(key);
    }
}
////////////////////////////////////////////////////////////////////

tcpclient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
////////////////////////////////////////////////////////////////////
#include <QtCore/QtCore>
#include <QtNetwork/QtNetwork>

#include <iostream>

#include <Windows.h>
////////////////////////////////////////////////////////////////////
class tcpClient : public QThread
{
    Q_OBJECT

    int socketDescriptor;
////////////////////////////////////////////////////////////////////
public:
    explicit tcpClient(int _socketDescriptor, QObject *_parent = 0);

    int getSocketDescriptor();
////////////////////////////////////////////////////////////////////
signals:
////////////////////////////////////////////////////////////////////
public slots:
////////////////////////////////////////////////////////////////////
private slots:
////////////////////////////////////////////////////////////////////
protected:
    void run();
////////////////////////////////////////////////////////////////////
};

#endif // TCPCLIENT_H

tcpclient.cpp

#include "tcpclient.h"
////////////////////////////////////////////////////////////////////
tcpClient::tcpClient(int _socketDescriptor, QObject *_parent) :
    QThread(_parent)
{
    std::cout << __FUNCTION__ << " " << GetCurrentThreadId() << " " << _socketDescriptor << std::endl;

    this->socketDescriptor = _socketDescriptor;
    this->moveToThread(this);
}
////////////////////////////////////////////////////////////////////
void tcpClient::run()
{
    std::cout << "START TCP CLIENT THREAD PID: " << GetCurrentProcessId() << " TID: " << GetCurrentThreadId() << std::endl;

    QTcpSocket* socket = new QTcpSocket();
    QSharedPointer<QTcpSocket> psocket = QSharedPointer<QTcpSocket>(socket, &QObject::deleteLater);

    socket->setSocketDescriptor(this->socketDescriptor);

    this->connect(socket, SIGNAL(disconnected()), this, SLOT(quit()));


    this->exec();

    socket->close();

    std::cout << "END TCP CLIENT THREAD PID: " << GetCurrentProcessId() << " TID: " << GetCurrentThreadId() << std::endl;
}
////////////////////////////////////////////////////////////////////
int tcpClient::getSocketDescriptor()
{
    std::cout << __FUNCTION__ << " " << GetCurrentThreadId() << std::endl;

    return this->socketDescriptor;
}
////////////////////////////////////////////////////////////////////


Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Сентябрь 19, 2012, 11:37 »

Ну как минимум вижу проблему в tcpClient::run().
deleteLater вызовется когда цикл обработки событий (this->exec()) уже закончит работу и ничего не удалит.
Объявите сокет просто как локальную переменную QTcpSocket socket без всяких указателей - он как раз без проблем по выходу из run удалится.

Просматривал по диагонали, так что вполне возможно, что это не единственная ошибка.
Записан
Alex_C
Гость
« Ответ #2 : Сентябрь 19, 2012, 11:40 »

Ключевое слово - deleteLater.
Записан
akaMDA
Гость
« Ответ #3 : Сентябрь 19, 2012, 11:46 »

QTсpSocket сделал локальным. При создании QSharedPoint<tcpClient> так же убрал deleteLater(). Однако утечка все равно есть.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.148 секунд. Запросов: 22.