Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Memory Leak issue due to dynamic creation of a QNetworkAccessManager object, locally inside a member function.
QtWS25 Last Chance

Memory Leak issue due to dynamic creation of a QNetworkAccessManager object, locally inside a member function.

Scheduled Pinned Locked Moved General and Desktop
14 Posts 4 Posters 3.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jeevan_reddy
    wrote on last edited by
    #1

    Hi All,

    How do we deal with memory leaks due to creation of a dymanic object locally inside a member function:

    Consider the scenario:

    I am working on client server application, where client application sends url requests to server and fetches information.

    @void MyClientApp::sendRequestToServer()
    {
    QNetworkAccessManager qnam;
    /
    Form the URL String */
    QString myurl ="http://" + this->server_address+":"+HTTP_PORT + get_country_list + "&CMSADDRESS=" + cmsIPAddress;
    qnam = new QNetworkAccessManager(this);

    QObject::connect(qnam, SIGNAL(finished(QNetworkReply*)),this,SLOT(handleServerResponse(QNetworkReply*)));
    return;

    }

    @
    In the above code object qnam is created dynamically, since the object created locally gets destroyed when the request method returns and the qnam cannot emit signal when the request returns coz it will out of scope.

    I create many such requests in my application and each creates the QNetworkAccessManager Object dynamically, but I do not delete the object since there is a signal/slot mechanism.

    Is there any way to balance memory leaks and yet not compromise on signal/slot functionality?

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Why are you creating a new QNAM each time you want to send a request ? You can create it once and use it multiple times, it would be cleaner.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jeevan_reddy
        wrote on last edited by
        #3

        Hi Gaist,

        Thanks for ur reply. You mean to say I create a member variable and use it.
        If I create a member variable, then I need to call delete each time, before allocating dynamic memory again in a new request.
        The only place where I can delete the QNAM is when I get a reply from the server and finish processing the response, in my case in slot handleServerResponse(). Am I thinking on the correct lines? or the other way is hold to hold each QNAM in a QList and delete the whole container when application is destroyed.

        Thanks,
        Jeevan

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          No, I meant to say: create only one QNAM and keep it.

          You didn't answer my question: why are you creating a QNAM for each request ? QNAM can handle several requests without any problem

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • J Offline
            J Offline
            jeevan_reddy
            wrote on last edited by
            #5

            I tried using a single QNAM to handle multiple requests but the Application always logs an error. My applications always throws up an error in the slot function dealing with processing QNetworkReply for the second request.

            Infact the QXmlStreamReader indicates an error when processing the network reply of second request.

            @QByteArray contents=reply->readAll();
            QXmlStreamReader reader(contents);
            if (reader.hasError())
            {
            qDebug() << "reader returned error";
            }@

            In my case QNam is successfull while dealing with single request but while sending multiple requests, it is failing miserably.

            The XMLReader is always indicating that the reply content has some error.

            1 Reply Last reply
            0
            • I Offline
              I Offline
              igorland
              wrote on last edited by
              #6

              Can you do something like:

              qnam->deleteLater();

              ?

              1 Reply Last reply
              0
              • V Offline
                V Offline
                vidar
                wrote on last edited by
                #7

                You wrote: "In the above code object qnam is created dynamically, since the object created locally gets destroyed when the request method returns".

                I don't think that this is the case.

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  .@ vidar, it is, an object created on the stack will be destroyed once it's out of scope.

                  .@ jeevan_reddy Can you show the complete code of sendRequestToServer and handleServerResponse ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    vidar
                    wrote on last edited by
                    #9

                    but qnam is created on the heap, on his example

                    1 Reply Last reply
                    0
                    • V Offline
                      V Offline
                      vidar
                      wrote on last edited by
                      #10

                      ... I mean, that's the reason for the memory leap. ;) Or let's say, the object that qnam points to is still alive after the method is left. So I don't really see a reason for why the signal emit should fail. The only reason could be a badly written connect function. ;)

                      1 Reply Last reply
                      0
                      • V Offline
                        V Offline
                        vidar
                        wrote on last edited by
                        #11

                        However, maybe I just got the description wrong.
                        I suggest a pool of QNetworkAccessManager objects.

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          jeevan_reddy
                          wrote on last edited by
                          #12

                          vldar: I really think you haven't got the problem I am facing here.

                          the issus is that If I create QNetworkAccessManager object dynamically, I have a memory leak to deal with.
                          If i create the object locally on the stack then I risk the failure of signal/slot mechanism, since the qnam object gets deleted once the method returns.

                          1 Reply Last reply
                          0
                          • J Offline
                            J Offline
                            jeevan_reddy
                            wrote on last edited by
                            #13

                            SGaist : Please find the sample code below uses only one QNetworkAccessManager object to handle multiple requests

                            @
                            MyClientApplication::MyClientApplication()
                            {
                            qnam = new QNetworkAccessManager() ;
                            }
                            void MyClientApplication::sendRequestConfigurationDetails()
                            {
                            /* Create a one-time execute timer to check connectivity with server */
                            download_started_flag = false;

                            /* Form the URL String */
                            QString myurl ="http://" + this->usr->server_address+":"+HTTP_PORT + "/serverrequest/cms.cgi?ACTION=getConfigDetails";
                            
                                QObject::connect(qnam, SIGNAL(finished(QNetworkReply*)),this,
                                                        SLOT(handleServerResponse(QNetworkReply*)));
                            QUrl url = myurl;
                            this->timeoutTimer->start();
                            reply = qnam->get(QNetworkRequest(url));
                            connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadStatus(qint64)));
                            return;
                            

                            }

                            void MyClientApplication::handleServerResponse(QNetworkReply* reply)
                            {
                            MMCommonError *com_class = new MMCommonError();
                            if ( this->timeoutTimer && this->timeoutTimer->isActive())
                            {
                            this->timeoutTimer->stop();
                            }
                            // error received?
                            if (reply->error() != QNetworkReply::NoError)
                            {
                            com_class->ShowError(HTTP_COMMUNICATION_ERROR);
                            reply->deleteLater();
                            this->setCursor(Qt::ArrowCursor);
                            return;
                            }

                            QByteArray contents=reply->readAll();
                            QXmlStreamReader reader(contents);
                            QString err;
                            int errcode=0;
                            while (!reader.atEnd())
                            {
                            reader.readNext();
                            if (reader.isStartElement())
                            {
                            if (reader.name() == "status")
                            {
                            /* It may be OK or error code */
                            err = reader.readElementText();
                            if (err.compare("OK") == 0) {
                            errcode = 0;
                            } else {
                            errcode = err.toInt();
                            break;
                            }
                            continue;
                            }

                                  if (reader.name() == "ServerAddress")
                                  {
                             /*do smethg */
                            

                            continue;
                            }
                            if(reader.name() == "CustomerID")
                            {
                            /*do smethg */
                            continue;
                            }
                            if(reader.name() == "Country")
                            {
                            QString country = reader.readElementText();
                            if (!country.isEmpty())
                            {
                            ui->countryComboBox->setEnabled(true);
                            ui->countryComboBox->clear();
                            ui->countryComboBox->insertItem(0,country);
                            this->currentCountry = country;
                            }
                            continue;
                            }
                            if(reader.name() == "City")
                            {
                            QString city = reader.readElementText();
                            if (!city.isEmpty())
                            {
                            ui->cityComboBox->setEnabled(true);
                            ui->cityComboBox->clear();
                            ui->cityComboBox->insertItem(0,city);
                            this->currentCity = city;
                            }
                            continue;
                            }
                            if(reader.name() == "Location")
                            {
                            QString location = reader.readElementText();
                            if (!location.isEmpty())
                            {
                            ui->locationComboBox->setEnabled(true);
                            ui->locationComboBox->clear();
                            ui->locationComboBox->insertItem(0,location);
                            this->currentLocation = location;
                            }
                            Continue;
                            }

                                }
                            

                            } /*xml reader has reached its end, end of while loop */

                                    if(isStatusConnected)
                                    {
                                           sendRequestCountryList();
                                    } 
                                          if (reader.hasError()) {
                                        qDebug() << "reader returned error";
                                        errcode = HTTP_COMMUNICATION_ERROR;
                              }
                              if (errcode != 0) {
                                        com_class->ShowError(errcode);
                                        reply->deleteLater();
                                        this->setCursor(Qt::ArrowCursor);
                                        return;
                              }
                              this->setCursor(Qt::ArrowCursor);
                              reply->deleteLater();
                              return;
                            

                            }

                            Note: the method sendRequestCountryList() creates another request and sends it to client. Basically we are sending second request from the method which handles the first request from server.

                            @

                            1 Reply Last reply
                            0
                            • SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              What is the exact error given by QXmlStreamReader ?

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved