内存泄漏与post请求和QNetworkAccessManager

时间:2013-12-02 13:36:49

标签: c++ qt post memory-leaks qnetworkaccessmanager

我正在制作一个使用大量计时器的程序,并以4秒的间隔在php脚本上进行在线发布。 我在QtCreator 5.1编码。我使用类似下面的类。

下面的一个只是填充一个任务列表,但是在整个8到12个小时的过程中,程序占用的内存会逐渐上升和上升。

使用这门课时我做错了什么? 我必须能够像我一样在网上发帖,大约每4到8秒。

这是一个用于处理我的一个过程的简单类:

标题文件: tasklistprocess.h

#ifndef TASKLISTPROCESS_H
#define TASKLISTPROCESS_H

#include <QThread>
#include <QtCore>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QListWidget>
#include <QTabWidget>

#include "globalhelper.h"
#include "securityinfo.h"

class TaskListProcess : public QThread
{
    Q_OBJECT
public:
    explicit TaskListProcess(QListWidget *obj_main, QTabWidget *tabs_main, QString user, QObject *parent = 0);

signals:
    void upTaskStorage(int key,QHash<QString,QString> item);

private:
    GlobalHelper gh;
    Securityinfo sci;
    QNetworkAccessManager *nam;
    QNetworkRequest request;
    QByteArray data;

    // this is the disposable params for reusage through out the class
    QUrlQuery params;
    QString post_data;
    QString user_name;
    QTimer *tasklist_tmr;

    bool get_task_list;

    QListWidget *obj;
    QTabWidget *tabs;

private slots:
    void setTaskList();
    void replyFinished(QNetworkReply *reply);
    void sendPost(QString file_name, QUrlQuery params);
};

#endif // TASKLISTPROCESS_H`

源文件: tasklistprocess.cpp

#include "tasklistprocess.h"

TaskListProcess::TaskListProcess(QListWidget *obj_main, QTabWidget *tabs_main, QString user, QObject *parent) :
    QThread(parent)
{
    user_name = user;
    get_task_list = false;
    obj = obj_main;
    tabs = tabs_main;
    tasklist_tmr = new QTimer(this);

    connect(this,SIGNAL(started()),this,SLOT(setTaskList()));
    connect(tasklist_tmr,SIGNAL(timeout()),this,SLOT(setTaskList()));

    nam = new QNetworkAccessManager(this);
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    request.setRawHeader( "User-Agent" , "Mozilla Firefox" );
    // here we connect up the data stream and data reply signals
    connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}

void TaskListProcess::setTaskList()
{
    qDebug() << "Your task list was set";
    bool in = false;
    if(!(tasklist_tmr->isActive()))
    {
        tasklist_tmr->start(10000);
        in = true;
    }
    if(!(get_task_list))
    {
        params.clear();
        params.addQueryItem("user_name", user_name);
        params.addQueryItem("logged_in", "1");
        sendPost("getTaskList.php",params);
        get_task_list = true;
    }
    else
    {
        if(post_data.contains("|*|"))
        {
            //here i retrieve a piece of information from a php script which is stored in a custom string format
            // here we clear the list for the new data to be put in
            if(obj->count()>0)
            {
                obj->clear();
            }
            int key = 0;
            foreach(QString inner_task,post_data.split("|*|"))
            {
                QHash<QString,QString> task_cont;
                //qDebug() << "         ";
                if(inner_task.contains("*,*"))
                {
                    foreach(QString task_val,inner_task.split("*,*"))
                    {
                        if(task_val.contains("*=*"))
                        {
                            QStringList key_pairs = task_val.split("*=*");
                            task_cont.insert(key_pairs[0],key_pairs[1]);
                            if(key_pairs[0] == "tt")
                            {
                                QString val_in;
                                if(key_pairs[1].length()>10)
                                {
                                    // this sets the title to the shortened version
                                    // if the string length is too long
                                    val_in = key_pairs[1].left(10) + "....";
                                }
                                else
                                {
                                    val_in = key_pairs[1];
                                }
                                obj->addItem("Task :" + QString::fromUtf8(key_pairs[1].toStdString().c_str()));
                            }
                        }
                    }
                }
                //task_storage.insert(key,task_cont);
                emit upTaskStorage(key,task_cont);
                key ++;
            }
        }
        get_task_list = false;
    }
    // here we're checking to see if they are looking at the task tab so it doesn't keep changing
    // back and forth between the tabs
    bool change = true;
    if(tabs->currentIndex() != 0)
    {
        change = false;
    }

    if(change)
    {
        tabs->setCurrentIndex(0);
    }else if(in)
    {
        tabs->setCurrentIndex(0);
    }
}

void TaskListProcess::replyFinished(QNetworkReply *reply)
{
    if (reply->error() != QNetworkReply::NoError) {
            qDebug() << "Error in" << reply->url() << ":" << reply->errorString();
            return;
        }
    QString data = reply->readAll().trimmed();
    post_data = data;
    if(get_task_list)
    {
        setTaskList();
    }
}

void TaskListProcess::sendPost(QString file_name, QUrlQuery params)
{
    post_data = "";
    QUrl url(sci.getHost() + file_name);

    url.setQuery(params);

    data.clear();
    data.append(params.toString().toUtf8());

    request.setUrl(url);
    nam->post(request, data);
}

3 个答案:

答案 0 :(得分:4)

来自Qt docs http://qt-project.org/doc/qt-5.1/qtnetwork/qnetworkaccessmanager.html

  

注意:请求完成后,由...负责   用户在适当的时候删除QNetworkReply对象。不要   直接在连接到finished()的插槽内删除它。您可以   使用deleteLater()函数。

我建议你在replyFinished()方法中调用reply->deleteLater()

答案 1 :(得分:2)

您应该在使用后为QNetworkReply对象调用deleteLater()。

注意:请求完成后,用户有责任在适当的时候删除QNetworkReply对象。不要在连接到finished()的插槽内直接删除它。您可以使用deleteLater()函数。

此处提供更多信息:http://harmattan-dev.nokia.com/docs/library/html/qt4/qnetworkaccessmanager.html

答案 2 :(得分:1)

谢谢大家的帮助。 它只是

中回复的“deleteLater()”
void replyFinished(QNetworkReply *reply)
{

}

它应该看起来像这样

void replyFinished(QNetworkReply *reply)
{
    // after all of your processing 
    reply->deleteLater();
}

这是一个很小的问题,但是让我疯了很长时间,所以我希望这会有所帮助