QNetworkRequest causes memory corruption

138 views Asked by At

I created a library which will handle all HTTP requests and parsing of response data in JSON format. When I called the method that includes get request in my main application (with GUI), I received a memory corruption error. So I added QEventLoop and a timer to wait for the response before proceeding to other processes. I was able to get the response data by calling QNetworkReply.readall(). I needed to get the char* value of the response data so I called the QNetworkReply.data() but it is empty. Why?

Here are the codes I wrote:

Library which handles HTTP requests:

void HttpRequest::getRequest(string param1, string param2)
{
    pManager_ = new QNetworkAccessManager(this);

    QUrl cUrl(sampleUrl);
    QNetworkRequest request(cUrl);
    request.setRawHeader(keyHeader.c_str(), param1.c_str());

    connect(pManager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
    connect(pManager_, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> & )), this,
            SLOT(handleSslErrors(QNetworkReply*, const QList<QSslError> & )));

    cUrl.addQueryItem("name", QString::fromStdString(param2));

    pManager_->get(request); // memory corruption error encountered in main application after calling this

    std::cout << "after calling get" << std::endl;
}

void HttpRequest::requestFinished(QNetworkReply *pReply)
{
    QByteArray responseData;

    std::cout << " request finished" << std::endl;
    int responseStatus = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    std::cout << " status code: " << responseStatus << std::endl;

    if(pReply->error())
        std::cout << " Error: " << pReply->errorString().toStdString() << std::endl;
    else
    {
        responseData = pReply->readAll();
        qDebug() << " Response data: " << responseData; 
        const char* pResponseData = responseData.data(); 
       qDebug() << "pResponseData: " << pResponseData ; 
        
        // parsing here
    }

    pReply->deleteLater();
    pManager_->deleteLater();
}

void HttpRequest::handleSslErrors(QNetworkReply *pReply, const QList<QSslError> & )
{
    std::cout << " SSL ERROR" << std::endl;
    int responseStatus = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
}

Main GUI application:

DialogTest::DialogTest(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogTest)
{

    // some codes here
    
    if(enabled)
    {
        HttpRequest::instance()->getInformation(param1, param2); // memory corruption happened here when I called getRequest() method with no event loop
    }
    
    // other threads here
}

Here is the code that uses QEventLoop:

void HttpRequest::getRequest(string param1, string param2)
{
    QTimer qTimer;
    QEventLoop loop;
    
    pManager_ = new QNetworkAccessManager(this);

    QUrl cUrl(sampleUrl);
    QNetworkRequest request(cUrl);
    request.setRawHeader(keyHeader.c_str(), param1.c_str());
   
    connect(&qTimer,SIGNAL(timeout()),&loop, SLOT(quit()));
    connect(pManager_, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));

    QNetworkReply *pReply = pManager_->get(request);

    qTimer.start(1000);
    loop.exec();

    int responseCode = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    std::cout << "status code: " << responseCode << std::endl;

    if(pReply->error())
    {
        std::cout << " Error: " << pReply->errorString().toStdString() << std::endl;
    }
    else
    {
        qDebug() << "[HttpRequest] Response data: " << pReply->readAll();
        QByteArray response = pReply->readAll(); // it printed this value: "{"count":3,"codes":["x00000A","x00000B","x00000C"]}" which is correct
        char* pResponseData = response.data(); 
       qDebug() << "pResponseData: " << pResponseData ; //it printed this: pResponseData:
    }

    delete pReply;
    delete pManager_;
}

I am expecting this response data from a HTTP get command: "{"count":3,"codes":["x00000A","x00000B","x00000C"]}"

Problem: What is the best way to implement this? I want to put all HTTP request in a library then call it my main application with GUI. Please note that:

  • When I use QEventLoop inside the library to wait for the response, QNetworkReply.data() is empty. I need the value of QNetworkReply.data() for parsing.
  • When I did not use QEventLoop and use signal and slot alone (as shown in the code above), memory corruption occurred in main application after executing HTTP get command. No response data is received.
1

There are 1 answers

1
Miguel Angel Pons On

an advice:

never use a direct delete for a QObject. BAD:

delete pReply;
delete pManager_;

Qt way,GOOD:

pReply->deleteLater();
pManager->deleteLater();

Better: no "new" (dynamic memory)

QNetworkAccessManager Manager_;
...
connect(&Manager_, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
 
..
pReply->deleteLater();