QNetworkRequest вызывает повреждение памяти

Я создал библиотеку, которая будет обрабатывать все HTTP-запросы и анализировать данные ответов в формате JSON. Когда я вызвал метод, который включает запрос на получение в моем основном приложении (с графическим интерфейсом), я получил ошибку повреждения памяти. Поэтому я добавил QEventLoop и таймер для ожидания ответа, прежде чем переходить к другим процессам. Мне удалось получить данные ответа, вызвав QNetworkReply.readall(). Мне нужно было получить значение char* данных ответа, поэтому я вызвал QNetworkReply.data(), но он пуст. Почему?

Вот коды, которые я написал:

Библиотека, которая обрабатывает 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();
}

Основное приложение с графическим интерфейсом:

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
}

Вот код, который использует 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_;
}

Я ожидаю эти данные ответа от команды HTTP get: {count:3,codes:[x00000A,x00000B,x00000C]}

Проблема: как лучше всего это реализовать? Я хочу поместить весь HTTP-запрос в библиотеку, а затем назвать его своим основным приложением с графическим интерфейсом. Обратите внимание, что:

  • Когда я использую QEventLoop внутри библиотеки для ожидания ответа, QNetworkReply.data() пуст. Мне нужно значение QNetworkReply.data() для синтаксического анализа.
  • Когда я не использовал QEventLoop и использовал только сигнал и слот (как показано в приведенном выше коде), в основном приложении произошло повреждение памяти после выполнения команды HTTP get. Данные ответа не получены.

person user123456    schedule 13.10.2020    source источник
comment
Любая помощь, пожалуйста...   -  person user123456    schedule 13.10.2020
comment
Пожалуйста, уточните проблему. Что вы имеете в виду под "pResponseData is empty"? Как вы тестируете/проверяете? Кроме того, вы указываете "pResponseData_ is empty" в одном месте — обратите внимание на завершающий «_» в pResponseData_. Это опечатка или должна быть переменная с именем pResponseData_?   -  person G.M.    schedule 13.10.2020
comment
Извините, это была опечатка. Я отредактировал свой пост и указал на проблему. pResponseData не имеет значения, когда я печатаю его с помощью cout, а cJSON_Parse() возвращает ошибку, поскольку оно не имеет значения.   -  person user123456    schedule 13.10.2020
comment
кто-нибудь может мне помочь, пожалуйста   -  person user123456    schedule 14.10.2020
comment
Извините, но вы так и не уточнили, что вы имеете в виду под pResponseData is empty -- почему вы так думаете? Тем более, что в комментарии к предыдущей строке указано the response data is correct. Это просто не складывается.   -  person G.M.    schedule 14.10.2020
comment
Привет @G.M., извини, я перепутал свой код. Я изменил его снова.   -  person user123456    schedule 14.10.2020
comment
Вы делаете слишком много ненужных и опасных шагов, копируя из pResponse в QByteArray, в char* и так далее. Ваш указатель char станет недействительным, как только QByteArray выйдет за пределы области видимости. Просто прочитайте документы Qt: doc.qt.io/qt-5/qbytearray. html#данные. Кроме того, избегайте использования QEventLoop.   -  person Giancarlo    schedule 14.10.2020
comment
@Giancarlo, я попробовал пример с документами Qt, но char * все еще пуст. char *data = new char[text.size() + 1]; strcpy(data, text.data()); // data is empty   -  person user123456    schedule 15.10.2020


Ответы (1)


совет:

никогда не используйте прямое удаление для QObject. ПЛОХОЙ:

delete pReply;
delete pManager_;

Qt кстати, ХОРОШО:

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

Лучше: без новых (динамическая память)

QNetworkAccessManager Manager_;
...
connect(&Manager_, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
 
..
pReply->deleteLater();
person Miguel Angel Pons    schedule 14.10.2020
comment
Спасибо, но это не решает проблему - person user123456; 15.10.2020