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)



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.