Russian Qt Forum

Qt => Работа с сетью => Тема начата: kambala от Июня 08, 2012, 20:36



Название: [РЕШЕНО] последовательное удаление и создание QNetworkAccessManager
Отправлено: kambala от Июня 08, 2012, 20:36
Здравствуйте. Добавил в приложение простенькую проверку обновлений: если с сайта1 нужная информация не была получена, то читаем с сайта2. Вот приблизительный код (класс выкинут):
Код
C++ (Qt)
QNetworkAccessManager *_qnam;
 
void checkUpdatesFromUrl(const QUrl &url)
{
   _qnam = new QNetworkAccessManager;
   connect(_qnam, SIGNAL(finished(QNetworkReply *)), SLOT(networkReplyFinished(QNetworkReply *)));
   _qnam->get(QNetworkRequest(url));
}
 
void networkReplyFinished(QNetworkReply *reply)
{
   QByteArray webpage = reply->readAll();
   reply->deleteLater();
   _qnam->deleteLater();
 
   QRegExp rx(QString("%1 v(.+)<\\/a>").arg(qApp->applicationName()));
   rx.setMinimal(true);
   if (rx.indexIn(webpage) != -1)
   {
       // всё ок - версия найдена
   }
   else
   {
       QUrl newUrl("сайт2");
       if (newUrl != reply->url())
           checkUpdatesFromUrl(newUrl);
   }
}
...
checkUpdatesFromUrl("сайт1");
Вопрос: не будет ли утечки памяти из-за _qnam, если управление переходит в else и там вызывается checkUpdatesFromUrl(newUrl)? Если да, то как это можно исправить (создавать _qnam в конструкторе я не хочу т.к. он мне больше нигде не нужен)?


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: Alex Custov от Июня 08, 2012, 21:05
не будет. Ты же указал, что старый объект нужно удалить, он и удалится немного погодя.


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: kambala от Июня 08, 2012, 21:14
спасибо. я думал, что раз _qnam потом начнет указывать на новый объект, то возможно старый "потеряется" и удален не будет. значит Qt сохраняет указатели на удаляемые таким образом объекты в каком-то списке/словаре и очищает этот контейнер когда "придет время"?


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: GreatSnake от Июня 08, 2012, 21:44
не будет. Ты же указал, что старый объект нужно удалить, он и удалится немного погодя.
Ещё как будет.

я думал, что раз _qnam потом начнет указывать на новый объект, то возможно старый "потеряется" и удален не будет.
Правильно думал.


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: alexis031182 от Июня 08, 2012, 21:53
Объясните, пожалуйста, почему не будет удалён? Событие об удаление объекта поместится в очередь событий. А то что происходит рекурсивный вызов функции, так там всего лишь указатель подменится, но старый объект останется существовать до наступления события удаления.


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: Alex Custov от Июня 08, 2012, 22:29
не будет. Ты же указал, что старый объект нужно удалить, он и удалится немного погодя.
Ещё как будет.

Ну чесслово :)

Код
C++ (Qt)
class O : public QObject
{
   Q_OBJECT
 
   public:
       O() : QObject()
       {
           qDebug("+O");
       }
 
       ~O()
       {
           qDebug("-O");
       }
};
 
int main(int argc, char *argv[])
{
   QCoreApplication app(argc, argv);
 
   O *o;
 
   o = new O;
   o->deleteLater();
 
   o = new O;
   o->deleteLater();
 
   o = new O;
   o->deleteLater();
 
   return app.exec();
}
 

Внимание, вопрос: сколько будет на экране "+O" и "-O"?


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: Alex Custov от Июня 08, 2012, 22:34
спасибо. я думал, что раз _qnam потом начнет указывать на новый объект, то возможно старый "потеряется" и удален не будет. значит Qt сохраняет указатели на удаляемые таким образом объекты в каком-то списке/словаре и очищает этот контейнер когда "придет время"?

я сперва даже не понял, думал что речь о чём-то другом, но ребят, как вам не стыдно? :) Указатель на объект - это не сам объект. Факт наличия или отсутствия указателя на существующий объект в памяти абсолютно не влияет на него, это не Java. Всё что делает метод deleteLater() - посылает отложенное событие самому себе (объекту), и он делает самоубийство через delete this;


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: alexis031182 от Июня 08, 2012, 23:21
Классно затролено ))


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: kambala от Июня 09, 2012, 00:07
Указатель на объект - это не сам объект. Факт наличия или отсутствия указателя на существующий объект в памяти абсолютно не влияет на него, это не Java.
да, это я знаю :)
Всё что делает метод deleteLater() - посылает отложенное событие самому себе (объекту), и он делает самоубийство через delete this;
теперь все ясно. спасибо за объяснение.

кстати тот код не компилируется если не выбросить Q_OBJECT - ругается на отсутствующую vtable, а main.moc не генерируется.


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: Alex Custov от Июня 09, 2012, 00:10
кстати тот код не компилируется если не выбросить Q_OBJECT - ругается на отсутствующую vtable, а main.moc не генерируется.

надо добавить в конец файла
Код:
#include "main.moc"
если имя исходного файла main.cpp, это я не скопировал.


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: kambala от Июня 09, 2012, 00:15
точно, спасибо. но там и без Q_OBJECT все работает как надо.


Название: Re: последовательное удаление и создание QNetworkAccessManager
Отправлено: GreatSnake от Июня 09, 2012, 07:13
я сперва даже не понял, думал что речь о чём-то другом, но ребят, как вам не стыдно? :)
Посыпаю голову пеплом. Стыдно :(