Troubled by memory leak problem in QNetworkAccessManager !!!
-
Hi,
I am recently using Qt to create a network module which involved Http requests.
I found a very disturbing problem when I used the QNetworkAccessManager and related classes.
For convienience, I simplified my code to example below. Each time I click the button, the Virtual Memory just keep growing up. I browsed other topics in forum, where I cannot find the reason. I hope you guys can help me on this.
Thanks.#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
manager = new QNetworkAccessManager;
connect(manager, SIGNAL(finished(QNetworkReply)), this, SLOT(onfinished(QNetworkReply*)));
}MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::onfinished(QNetworkReply *reply)
{
qDebug() << reply->readAll();
reply->abort();
reply->close();
reply->deleteLater();
}void MainWindow::on_pushButtonLogin_clicked()
{
isNeedVcode();
}int MainWindow::isNeedVcode()
{
QNetworkRequest request;
//QString strurl = QString("http://www.baidu.com");
QString strurl = QString("http://check.ptlogin2.qq.com/check?&uin=870603663");
request.setUrl(QUrl(strurl));
//
request.setRawHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
//
manager->get(request);return 0;
}
-
Are you getting your qDebug() output from the onfinished() slot? If not, I'm guessing it's because your connect statement is incorrect; your data types of your SIGNAL and SLOT do not match (QNetworkReply vs. QNetworkReply*). Since your onfinished() slot wouldn't ever be called because of the bad connect statement, your QNetworkReply never gets deleted either.
-
It's a mistake when I copy the code from other place.
Here are the exact code below that I just write for this network test.
The bigger the count of request sent in a loop, the more consumed virtual memory of this program.
And after finished all of these http requests, the Virtual Memory of this program did not reduce.
However, when I add a qWait(1) between every request, the memory will not goes up when the number of sent requests grows. But the memory still doesn't go down when I delete everything I used to access network.
It seems when concurrently create and send a large amount of http requests through QNetworkAccessManager, the memory leakage will happen.//Header**
#ifndef NETWORK_H
#define NETWORK_H#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QTest>class NetWork : public QObject
{
Q_OBJECT
private:
explicit NetWork(QObject *parent = 0);public:
static NetWork *Instance();void Post(const QUrl &url, const QByteArray content); void Get(const QUrl &url); void Clean(); void Print(); QNetworkAccessManager *Manager();
signals:
public slots:
void SlotPostFinished();
void SlotCountDestroyed();private:
static NetWork *_network;
QNetworkAccessManager *_manager;public:
qint32 _countOk, _countError, _countSent, _countDestroyed;
};class UnitTest_Network : public QObject{
Q_OBJECT
public:
explicit UnitTest_Network(QObject *parent = 0);private slots:
void test10ps();
void test10ps_data();
};#endif // NETWORK_H
//CPP
#include "network.h"NetWork::NetWork(QObject *parent) :
QObject(parent)
{
_manager = new QNetworkAccessManager(this);
}NetWork *NetWork::_network = NULL;
NetWork *NetWork::Instance()
{
if(_network == NULL){
_network = new NetWork();
}
return _network;
}void NetWork::Post(const QUrl &url, const QByteArray content)
{
QNetworkRequest request(url);request.setRawHeader("Content-Type", "application/json"); QNetworkReply *reply = _manager->post(request, content); connect(reply, SIGNAL(finished()), this, SLOT(SlotPostFinished())); connect(reply, SIGNAL(destroyed()), this, SLOT(SlotCountDestroyed()));
}
void NetWork::Get(const QUrl &url)
{
QNetworkRequest request(url);request.setRawHeader("Content-Type", "application/json"); QNetworkReply *reply = _manager->get(request); connect(reply, SIGNAL(finished()), this, SLOT(SlotPostFinished()), Qt::DirectConnection); connect(reply, SIGNAL(destroyed()), this, SLOT(SlotCountDestroyed()));
}
void NetWork::Clean()
{
_countOk = 0;
_countError = 0;
_countSent = 0;
_countDestroyed = 0;
}void NetWork::Print()
{
qDebug("10 ps:\t Sent = %d, Ok = %d, Error = %d, Destroyed = %d",
_countSent, _countOk, _countError, _countDestroyed);
qApp->processEvents();
}QNetworkAccessManager *NetWork::Manager()
{
return _manager;
}void NetWork::SlotPostFinished()
{
QNetworkReply reply = (QNetworkReply)sender();
qint32 statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(!reply->error()){
_countOk++;
}
else{
_countError++;
}
reply->readAll();
reply->abort();
reply->close();
reply->deleteLater();
}void NetWork::SlotCountDestroyed()
{
_countDestroyed++;
}void UnitTest_Network::test10ps()
{}
void UnitTest_Network::test10ps_data()
{
QTest::addColumn<qint32>("hehe");
NetWork::Instance()->Clean();
qDebug("Test 10 ps ...");qint32 count = 500; qDebug("Starting ..."); QTest::qWait(1000); for(int j=0; j<10; j++){ for(int i=0; i<count; i++){ NetWork::Instance()->Post(QString("http://192.168.0.90/rest/Logs/"), QByteArray("{\"reserve\" : \"\", \"logTime\" : 1410865245827, \"machineId\" : \"0023\", \"operationCode\" : \"x\", \"deviceNum\" : \"b\", \"deviceAttribute\" : \"5\",\"parameter\" :\"0624\", \"checksum\" : -111, \"serialNum\" : \"92bb\"}")); NetWork::Instance()->_countSent++;
// QTest::qWait(1);
// qApp->processEvents();
}
qDebug("LOOP No.%d", j);
}while(1){ if(NetWork::Instance()->_countSent == NetWork::Instance()->_countError + NetWork::Instance()->_countOk) break; NetWork::Instance()->Print(); QTest::qWait(5000); } qDebug("delete manager ..."); QTest::qWait(5000); NetWork::Instance()->Manager()->deleteLater(); qDebug("wait ..."); QTest::qWait(5000); qDebug("delete network ..."); NetWork::Instance()->deleteLater(); QTest::qWait(5000); qDebug("End ..."); QTest::qWait(10000);
}
UnitTest_Network::UnitTest_Network(QObject *parent)
{
}QTEST_MAIN(UnitTest_Network)