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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Помогите найти leaks?  (Прочитано 16316 раз)
Kainit
Гость
« Ответ #15 : Ноябрь 08, 2007, 16:33 »

pastor,
1. Вы зря, dumpObjectTree() - очень приятный метод QObject-а и код его вы можете посмотреть в исходниках Qt...
2. Если бы Nalsur1982 привёл полный код, мы бы зарылись читая километры ненужного нам материала. Вполне достаточно знания того, что приведённый код порождает лики (пусть он даже и не несёт особого смысла).

Nalsur1982
1. Мне стало интересно. А можно готовый проектик куда-нибудь скинуть, чтобы его погонять можно было? Ну не вижу я здесь мест для ликов.
« Последнее редактирование: Ноябрь 08, 2007, 16:35 от Kainit » Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #16 : Ноябрь 08, 2007, 16:50 »

pastor,
1. Вы зря, dumpObjectTree() - очень приятный метод QObject-а и код его вы можете посмотреть в исходниках Qt...
2. Если бы Nalsur1982 привёл полный код, мы бы зарылись читая километры ненужного нам материала. Вполне достаточно знания того, что приведённый код порождает лики (пусть он даже и не несёт особого смысла).

2 Kainit

1) Я упустил из внимания, что dumpObjectTree это метод QObject. Я подумал, что это самописный метод
2) Возможно, остальной код и порождает лики, а не тот код, что приведён. Извините, но телепаты в отпуске, чтобы без ТОЧНОГО кода определить лик.

имхо, код проги необходимо пересмотреть, ибо уже в преведённом коде есть проблемные места  и совсем непонятна роль некоторого кода... Если я неправ, прошу меня поправить
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Nalsur1982
Гость
« Ответ #17 : Ноябрь 08, 2007, 17:17 »

ServerConnection будет выполнять другие действия, просто для облегчения понимания я их не привожу и при отладке тоже не использую. То есть это и есть весь рабочий код. Можно просто вставить в пустой проект.  (Исправлю баг и займусь остальным)

Вот именно, пока просто висит, а память уже куда-то утекает. И не пойму в чем дело.

Могу куда-нибудь выложить или по почте лучше отослать.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #18 : Ноябрь 08, 2007, 18:56 »

Попробуйте закоментить тело метода void TcpServer::incomingConnection(). Будет ли в таком случае течь память?
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Kainit
Гость
« Ответ #19 : Ноябрь 08, 2007, 21:16 »

Цитировать
Могу куда-нибудь выложить или по почте лучше отослать.
да на любой файлошарер... на тот же http://www.ifolder.ru/
Записан
Nalsur1982
Гость
« Ответ #20 : Ноябрь 09, 2007, 09:55 »

Без incomingConnection() утечки конечно не будет. Так как вся утечка происходит при коннекте клиентов.

http://webfile.ru/1587628 ссылка на сорцы. + клиентская часть которая коннектится к серверу. (~10к)

http://webfile.ru/1587641 сорцы и бинари
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #21 : Ноябрь 09, 2007, 11:34 »

Сразу вопрос. Вот код:

Код:
TcpClient::TcpClient( QObject *parent) 
: QObject(parent)
{
qDebug() << "TcpClient::TcpClient()";
socket = new QTcpSocket();
socket->connectToHost(QHostAddress("127.0.0.1"), (quint16)5406);
}

TcpClient::~TcpClient()
{
qDebug() << "TcpClient::~TcpClient()";
socket->disconnectFromHost();
}

а где же удаление socket? Или укажи парента в конструкторе или удаляй явно в деструкторе. Вот лик уже найден в Client
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #22 : Ноябрь 09, 2007, 11:42 »

Ещё раз хочу сосредоточить ваще внимание на ServerConnection. Вы хотите добиться мультипотоковости? Читать данные в отдельном потоке? Увы у вас этого нет. ServerConnection::receiveData() не будет выполнена в отдельном потоке! Поток "сосредоточен" в методе run() . Даже если код из receiveData() перенести в run() это не будет безопасно, т.к. QTcpSocket являеться reentrant а не
thread-safe. Если будут вопросы, задавайте
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Nalsur1982
Гость
« Ответ #23 : Ноябрь 09, 2007, 12:10 »

Насчет TcpClient - это просто класс для теста, чтобы ускорить процесс обнаружения ошибки. Я также пробовал с Putty коннектится - та же проблемма.

В методе ServerConnection::run() будет создан экземпляр класса с функциональностью протокола, создан connect(..) сигнала ServerConnection (пока его нет) который будет вызываться receiveData() после принятия всего блока данных из сети. И через QByteArray передаваться в слот класса протокола для обработки.

А может все перемудрил, может можно проще? Идея такова: к серверу коннектятся удаленные хосты и по стандартному протоколу запрашивают данные. Сервер их будет собирать с других машин (возможно по другим протоколам) и хранить данные в общей базе. Короче, конвертор протоколов с возможностью хранения и обраьотки.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #24 : Ноябрь 09, 2007, 14:19 »

Скомпилил ваши примеры. Проверил LinkManager. Увеличение объёма используемой памяти имхо связано с методом
nextPendingConnection ().

Цитировать
The socket is created as a child of the server, which means that it is automatically deleted when the QTcpServer object is destroyed. It is still a good idea to delete the object explicitly when you are done with it, to avoid wasting memory.


Я переделал на дискрипторы, проблема сразу пропала
« Последнее редактирование: Ноябрь 09, 2007, 14:44 от pastor » Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #25 : Ноябрь 09, 2007, 14:48 »

Вот код:

Код:
class TcpServer : public QTcpServer
{
Q_OBJECT
public:
TcpServer(QObject *parent = 0);
~TcpServer();

protected:
void incomingConnection(int socketDescriptor);
};

Код:
TcpServer::TcpServer( QObject *parent ) 
: QTcpServer(parent)
{
qDebug() << "TcpServer::TcpServer()";
listen(QHostAddress::Any, 5406);
}

TcpServer::~TcpServer()
{
qDebug() << "TcpServer::~TcpServer()";
}

void TcpServer::incomingConnection(int socketDescriptor)
{
qDebug() << "TcpServer::incomingConnection()";
ServerConnection *conn = new ServerConnection(socketDescriptor, this);
connect(conn, SIGNAL(finished()), conn, SLOT(deleteLater()));
conn->start();
}

Код:
class ServerConnection : public QThread
{
Q_OBJECT
public:
ServerConnection(int socketDescriptor, QObject *parent = 0);
~ServerConnection();

void run();

private:
int socketDescriptor;
};

Код:
ServerConnection::ServerConnection( int socketDescriptor, QObject *parent) 
: QThread(parent), socketDescriptor(socketDescriptor)
{
qDebug() << "ServerConnection::ServerConnection()";
}

ServerConnection::~ServerConnection()
{
qDebug() << "ServerConnection::~ServerConnection()";
}

void ServerConnection::run()
{
qDebug() << "ServerConnection::run()";
QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
        return;
    }
            //we're in the new thread! ;)
//here we can read or write data

tcpSocket.disconnectFromHost();
    if (tcpSocket.state() != QAbstractSocket::UnconnectedState )
tcpSocket.waitForDisconnected();
}
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Nalsur1982
Гость
« Ответ #26 : Ноябрь 09, 2007, 15:22 »

2 pastor

Может я торможу где-то? Откомпилил твой код и запустил - все нормально.
Затем закомментировал  строчку tcpSocket.disconnectFromHost() (чтобы клиент разрывал связь), в итоге за 10 мин утекло 4метра. Может я что-то не понимаю?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #27 : Ноябрь 09, 2007, 15:35 »

Я закоментил тоже эту строку, все нормально:

Код:
void ServerConnection::run()
{
qDebug() << "ServerConnection::run()";
QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
        return;
    }


    //tcpSocket.disconnectFromHost();
    //if (tcpSocket.state() != QAbstractSocket::UnconnectedState )
    // tcpSocket.waitForDisconnected();
}

Память стоит на месте 6,4 Мб. Qt 4.3.2
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Nalsur1982
Гость
« Ответ #28 : Ноябрь 09, 2007, 15:47 »

Сорри я поторопился с выводами!
На 2Мб увеличилась память и больше вроде не поднимается. С 9.3Мб до ~11.3Мб и остановилась вроде. Подожду еще часик.

Спасибо всем кто откликнулся!
Записан
pl_mix
Гость
« Ответ #29 : Июль 17, 2011, 21:09 »

Кому интересно могу поделиться своим опытом с данной проблемой. Кодил клиент-сервер, при каждом конекте утекало до 6 метров, как оказалось хоть я и слал когда нужно было finished он не убивал нить, поэтому и была утечка. Нашёл эту тему на форуме, натолкна на мысль (за что Вам огромное спасибо) обратить внимание на то  как я при этом убиваю сокет. Покумекал и  решил перед вызовом deleteLater() вызывать слот закрытия конекта:
Код:
void ServerCore::incomingConnection(int socketDescriptor)
   {

     
       UserSession* user = new UserSession; // нить

        user->moveToThread(user);
        connect(user,SIGNAL(finished()),    //важен порядок
              user,SIGNAL(signalClose()));
        connect(user,SIGNAL(finished()),
               user,SLOT(deleteLater()));
в самой нити:
Код:
void UserSession::run()
{
 _client = new nSocket(_nsock,this) //потомок QTcpSocket
......//нужные связки сигналов и слотов для обратотки
connect(this, SIGNAL(signalClose()),_client,SLOT(slotCloseSession()));
connect(_client,SIGNAL(disconnected()),this, SLOT(quit()));
exec();
и на последок слот в сокете:
Код:
void nSocket::slotCloseSession()
{
   if( state() == QTcpSocket::ConnectedState)
           close();

}
и о чудо, всё сухо...утечки нет))
 Конечно можна найти и более гибкое решение... через создание отдельной функции которая предварительно шлёт сигнал для закрытия сокета , а потом чтоб посылала finished() и тд и тп. но просто у меня в коде во всех проверках  и защитах стоит просто сигнал  finished() для закрытия при некоретностях и для переделки надо время, а там на быстрою руку для проверки сойдёт.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


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