You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QNetworkAccessManager在QThread中重复调用post为何出现内存泄漏?

为何移至QThread实例的自定义对象中重复运行的这段代码会产生内存泄漏?

运行环境:Ubuntu 20.04、x86_64 CPU、Qt 5.14.2,每次调用以下代码约泄漏8字节,移除post()调用后未检测到泄漏。

泄漏复现代码:

void QCustomHTTPManager::compare()
{
    // custom code to create request and multiPart content
    QNetworkReply *reply = networkaccessmanager->post(request,&multiPart);
    connect(reply,&QNetworkReply::finished,eventloop,&QEventLoop::quit);
    eventloop->exec();
    emit compared();
    reply->deleteLater();
}

无泄漏对照代码:

void QCustomHTTPManager::compare()
{
     // custom code to create request and multiPart content
    QTimer::singleShot(1,eventloop,&QEventLoop::quit);
    eventloop->exec();
    emit compared();
}

泄漏原因及修正方案

  • 核心问题:QNetworkReply的deleteLater()无法被执行

    1. deleteLater()的工作逻辑是向对象所在线程的事件队列发送删除事件,只有当该线程的事件循环处于运行状态时,这个事件才会被处理,进而销毁对象。
    2. 你的代码中,eventloop->exec()阻塞当前线程直到finished信号触发,循环退出后调用reply->deleteLater(),但此时当前线程的事件循环已经停止,没有机会处理删除事件,导致reply对象始终无法被释放,每次调用都会积累内存泄漏。
    3. 额外隐患:你传递栈对象multiPart的地址给post(),如果未设置multiPart->setParent(reply),multiPart的资源无法随reply一同释放,会加重泄漏问题。
  • 修正方法

    • 放弃局部事件循环的阻塞方式,改用信号槽连接reply的finished信号到处理函数,确保事件循环能正常处理删除事件:
      void QCustomHTTPManager::compare()
      {
          // custom code to create request and multiPart content
          multiPart->setParent(nullptr);
          QNetworkReply *reply = networkaccessmanager->post(request, multiPart);
          connect(reply, &QNetworkReply::finished, this, [=](){
              emit compared();
              reply->deleteLater();
          });
      }
      
    • 如果必须使用局部事件循环,在调用deleteLater()后手动触发一次事件处理,让删除事件执行:
      void QCustomHTTPManager::compare()
      {
          // custom code to create request and multiPart content
          QNetworkReply *reply = networkaccessmanager->post(request,&multiPart);
          connect(reply,&QNetworkReply::finished,eventloop,&QEventLoop::quit);
          eventloop->exec();
          emit compared();
          reply->deleteLater();
          QCoreApplication::processEvents(); // 手动处理事件队列,执行删除操作
      }
      
    • 务必为multiPart设置父对象为reply:multiPart->setParent(reply);,确保其随reply一同释放。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:15:27