Я создал библиотеку, которая будет обрабатывать все 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. Данные ответа не получены.
"pResponseData is empty"
? Как вы тестируете/проверяете? Кроме того, вы указываете"pResponseData_ is empty"
в одном месте — обратите внимание на завершающий «_» вpResponseData_
. Это опечатка или должна быть переменная с именемpResponseData_
? - person G.M.   schedule 13.10.2020pResponseData is empty
-- почему вы так думаете? Тем более, что в комментарии к предыдущей строке указаноthe response data is correct
. Это просто не складывается. - person G.M.   schedule 14.10.2020char *data = new char[text.size() + 1];
strcpy(data, text.data()); // data is empty
- person user123456   schedule 15.10.2020