简体   繁体   English

QNetworkRequest 导致内存损坏

[英]QNetworkRequest causes memory corruption

I created a library which will handle all HTTP requests and parsing of response data in JSON format.我创建了一个库,它将处理所有 HTTP 请求并解析 JSON 格式的响应数据。 When I called the method that includes get request in my main application (with GUI), I received a memory corruption error.当我在主应用程序(使用 GUI)中调用包含 get 请求的方法时,我收到了内存损坏错误。 So I added QEventLoop and a timer to wait for the response before proceeding to other processes.所以我添加了 QEventLoop 和一个计时器来等待响应,然后再继续其他进程。 I was able to get the response data by calling QNetworkReply.readall().我能够通过调用 QNetworkReply.readall() 来获取响应数据。 I needed to get the char* value of the response data so I called the QNetworkReply.data() but it is empty.我需要获取响应数据的 char* 值,所以我调用了 QNetworkReply.data() 但它是空的。 Why?为什么?

Here are the codes I wrote:下面是我写的代码:

Library which handles HTTP requests:处理 HTTP 请求的库:

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:这是使用 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"]}"我期待来自 HTTP get 命令的响应数据: "{"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.我想将所有 HTTP 请求放在一个库中,然后使用 GUI 将其称为我的主应用程序。 Please note that:请注意:

  • When I use QEventLoop inside the library to wait for the response, QNetworkReply.data() is empty.当我在库中使用 QEventLoop 等待响应时, QNetworkReply.data() 为空。 I need the value of QNetworkReply.data() for parsing.我需要 QNetworkReply.data() 的值进行解析。
  • 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.当我没有使用 QEventLoop 并单独使用信号和插槽时(如上面的代码所示),执行 HTTP get 命令后主应用程序中发生内存损坏。 No response data is received.没有收到响应数据。

an advice:一个建议:

never use a direct delete for a QObject.永远不要对 QObject 使用直接删除。 BAD:坏的:

delete pReply;
delete pManager_;

Qt way,GOOD: Qt方式,好:

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

Better: no "new" (dynamic memory)更好:没有“新”(动态内存)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM