QNetworkAccessManager内存泄露问题的后续

62 篇文章 8 订阅

先说结论,升级QT到最新版本即可解决!确认官方bug!

折腾了四五天了,最后在Qt论坛找到了答案,确认有问题的版本为qt-opensource-windows-x86-5.14.1.exe:

确认已经修复问题的版本qt-opensource-windows-x86-5.12.10和qt-opensource-windows-x86-5.9.9.exe:

因为5.9.9和5.14.1关于的版本显示一致,所以通过安装文件的名字区分比较好!

===============分割线===================

被这个问题困扰了几天,都想换个http库了,但是为了尽量使用纯Qt代码,于是只能继续尝试,改进类。

修改思路:

1.外部传递manager,公用一个,避免反复申请,析构。

2.取消继承自QObject,避免未知问题。

3.注意断开信号与槽(因为不知道内部信号与槽源代码,怀疑这个也可能导致内存泄露)

4.该关闭的关闭,该删除的删除

#ifndef CLIENTPROGRESS_H
#define CLIENTPROGRESS_H

#include <QObject>
#include <QNetworkRequest>
#include <QNetworkReply>

class ClientProgress
{
public:
    explicit ClientProgress(QNetworkAccessManager* pManager);
    ~ClientProgress();

public:
    int CheckClientProgress(std::string strHost, std::string strProgressFilePathName, std::string& strInfo);

private:
    int parseReplyData(QNetworkReply* reply, QByteArray& data);
    int requestClientUrl(const QString& strHost, const QByteArray& baPostData, QByteArray& baAnswer, int nTimeoutSeconds = 10);

    void setRequestHeader(QNetworkRequest &request)
    {
        request.setRawHeader("Content-Type", "charset='utf-8'");
        request.setRawHeader("Content-Type", "application/json");
    }

private:
    QNetworkAccessManager* m_naManager;
signals:

};

#endif // CLIENTPROGRESS_H

实现:

#include "ClientProgress.h"
#include <QNetworkAccessManager>
#include <QEventLoop>
#include <QTimer>

#include "taskFuncList.h"
#include "JsonParser.h"

ClientProgress::ClientProgress(QNetworkAccessManager *pManager)
{
    Q_ASSERT(pManager != nullptr);

    m_naManager = nullptr;

    if (pManager)
    {
        m_naManager = pManager;
    }
}

ClientProgress::~ClientProgress()
{
}

int ClientProgress::CheckClientProgress(std::string strHost, std::string strProgressFilePathName, std::string &strInfo)
{
    QStringList lKeys, lValues;
    lKeys.push_back("ip");
    lKeys.push_back("fun");
    lKeys.push_back("file");
    lValues.push_back(strHost.c_str());
    lValues.push_back(QString::number(enProgress));
    lValues.push_back(strProgressFilePathName.c_str());
    QByteArray baPostData = JsonParser::StringList2ByteArray(lKeys, lValues);

    QByteArray baReply;
    if (requestClientUrl(strHost.c_str(), baPostData, baReply, 2) == 0)
    {
        QString strProgress;
        if (JsonParser::ParseRootKeyValue(baReply, "progress", strProgress) == 0)
        {
            QStringList lProgress =  strProgress.split(",");

            if (lProgress.size() >= 2)
            {
                int nProgress = lProgress[0].toInt();
                if (nProgress >= 0 && nProgress <= 100)
                {
                    strInfo = lProgress[1].toUtf8().data();

                    return nProgress;
                }
            }
        }
    }

    return 0;
}

int ClientProgress::parseReplyData(QNetworkReply *reply, QByteArray &data)
{
    if (reply == nullptr)
    {
        return -1;
    }

    if(reply->error() != QNetworkReply::NoError)
    {
        return -2;
    }
    else
    {
        //输出内容
        data = reply->readAll();
    }

    return 0;
}

int ClientProgress::requestClientUrl(const QString &strHost, const QByteArray &baPostData, QByteArray &baAnswer, int nTimeoutSeconds)
{
    if (m_naManager == nullptr)
    {
        return -1;
    }

    QString strCmdUrl = QString("http://") + strHost + ":" + QString::number(9998);

    QNetworkRequest request(strCmdUrl);
    setRequestHeader(request);

    QNetworkReply* reply = m_naManager->post(request, baPostData);
    QEventLoop eventloop;
    QMetaObject::Connection conRet = QObject::connect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
    Q_ASSERT(conRet);

    QTimer timer;
    timer.singleShot(nTimeoutSeconds * 1000, &eventloop, SLOT(quit()));
    timer.start();

    eventloop.exec(QEventLoop::ExcludeUserInputEvents);

    if (timer.isActive())
    {
        QByteArray baReply;
        if (parseReplyData(reply, baReply) == 0)
        {
            //超时,未知状态
            QObject::disconnect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
            reply->abort();
            reply->close();
            reply->deleteLater();
            baAnswer = baReply;

            return 0;
        }
    }

    //超时,未知状态
    QObject::disconnect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
    reply->abort();
    reply->close();
    reply->deleteLater();

    return -1;
}

继续长时间测试中,目前测试的结果是1、3、4无效,正在测试2,看起来初见成效,后续将记录测试结果!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值