Название: Утечка памяти в многопточном Tcp server
Отправлено: 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; } ////////////////////////////////////////////////////////////////////
Название: Re: Утечка памяти в многопточном Tcp server
Отправлено: LisandreL от Сентябрь 19, 2012, 11:37
Ну как минимум вижу проблему в tcpClient::run(). deleteLater вызовется когда цикл обработки событий (this->exec()) уже закончит работу и ничего не удалит. Объявите сокет просто как локальную переменную QTcpSocket socket без всяких указателей - он как раз без проблем по выходу из run удалится.
Просматривал по диагонали, так что вполне возможно, что это не единственная ошибка.
Название: Re: Утечка памяти в многопточном Tcp server
Отправлено: Alex_C от Сентябрь 19, 2012, 11:40
Ключевое слово - deleteLater.
Название: Re: Утечка памяти в многопточном Tcp server
Отправлено: akaMDA от Сентябрь 19, 2012, 11:46
QTсpSocket сделал локальным. При создании QSharedPoint<tcpClient> так же убрал deleteLater(). Однако утечка все равно есть.
|