程序编译运行过程很顺利,测试的时候也没发现什么问题。但后来我随手上传了一个1G大小的文件,发现每次文件上传到70%左右的时候程序就崩溃了,小文件就没这个问题。急忙打开任务管理器,这才发现上传文件的时候,程序内存占用会随着上传进度的增加而增加,上传1G文件的时候内存最多会吃到1.5G,这时候程序申请不到更多内存了,我又没做检查,当然就会崩溃掉。

限制上传文件大小这种事我是不会做的,毕竟一个上传工具占用内存比PS都高实在不科学。注意到文件上传完成之后内存会立即回到正常值,显然原因并不是我忘记释放内存而是内存释放不及时,这样看来唯一可疑的地方就是上面chunkUpload函数里面的reply->deleteLater()那一句了吧。于是我写了个方法监听reply的销毁时机,果然每一块上传完成之后reply没有销毁,直到文件全部上传完毕之后才输出一大堆“I’m destroyed…”的信息。

根据Qt文档的说明,QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象。我在这里使用deleteLater只是因为Qt文档里推荐这么做而已,其他并没多想。是这样的话一切都说得通了,因为chunkUpload函数是在一个while循环里,程序还没来得及处理这个event就立即进行下一块传输了,传输过程中生成的QNetworkReply以及它关联的QBufferQHttpMultiPart当然也就来不及删除了。崩溃原因找到了。你不就是来不及处理销毁对象的event嘛,手动让你处理下不就行了?于是修改upload函数代码如下:

1
2
3
4
5
6
7
void upload()
{
while (NOT_FINISHED) {
chunkUpload(item, CHUNK_SIZE);
qApp->processEvents(); // 让主程序把消息队列中的QEvent处理完
}
}

编译、运行,内存占用依然没有改变,看样子加这一行用处不大。再次查询QObject::deleteLater()的文档,发现这样一句话:

…for the object to be deleted, the control must return to the event loop from which deleteLater() was called.

这么说来,deleteLater销毁QObject的唯一时机就是程序返回主消息循环以后了呢。无奈只能放弃deleteLater。考虑到每次return前都要手动delete亦或是使用goto语句实在都不够优雅,所以利用Qt自带的QScopedPointer,修改chunkUpload函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int chunkUpload(UploadItem *item, const qint64 &chunkSize)
{
Q_ASSERT(item != 0); // ... QNetworkRequest request;
QScopedPointer<QNetworkReply> reply;
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QBuffer* buffer = new QBuffer(multiPart);
QEventLoop loop;
QTimer timer; // ... append fields to multiPart ... request.setUrl(UPLOAD_URL);
reply.reset(networkManager->post(request, multiPart));
multiPart->setParent(reply.data()); // ... event loop ... if (reply->isRunning())
reply->abort(); if (reply->error() != QNetworkReply::NoError)
return -1; // ... deal with the reply ... return 0;
}

问题解决。

https://blog.yeatse.com/2015/03/18/qobject-deletelater-usage/

QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象 good的更多相关文章

  1. Qt事件机制(是动作发生后,一种通知对象的消息,是被动与主动的总和。先处理自己队列中的消息,然后再处理系统消息队列中的消息)

    Qt事件机制 Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.. Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. Qt事件的类型很多, 常见的qt的事件如下: 键盘事 ...

  2. 一步步搭建自己的轻量级MVCphp框架-(四)一个国产轻量级框架Amysql源码分析(3) 总进程对象

    AmysqlProcess类,框架的总进程对象 ./Amysql/Amysql.php 下面还是和以前一样,先上代码~ class AmysqlProcess { public $AmysqlCont ...

  3. 使用jQuery匹配文档中所有的li元素,返回一个jQuery对象,然后通过数组下标的方式读取jQuery集合中第1个DOM元素,此时返回的是DOM对象,然后调用DOM属性innerHTML,读取该元素 包含的文本信息

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. python在交互模式下直接输入对象后回车,调用的是对象的__repr__()方法,这个方法表示的是一个编码,用print+对象是调用对象的__str__方法

    交互模式下调用对象的__repr__()方法,这个方法表示的是一个编码 >>> u"国庆节快乐"u'\u56fd\u5e86\u8282\u5feb\u4e50' ...

  5. JS对象 Array 数组对象 数组对象是一个对象的集合,里边的对象可以是不同类型的。数组的每一个成员对象都有一个“下标”,用来表示它在数组中的位置,是从零开始的

    Array 数组对象 数组对象是一个对象的集合,里边的对象可以是不同类型的.数组的每一个成员对象都有一个"下标",用来表示它在数组中的位置,是从零开始的 数组定义的方法: 1. 定 ...

  6. C# 基础才是重中之重~对象的生与死

    为何要写 之所以写这篇文章,完全是因为学生们在实际开发中遇到的问题,一个对象占用的内存空间总不被释放,导致系统内存不断攀升,其最主要原因是我们对“对象的生与死”不清楚,或者从来没有认真去考虑过这件事, ...

  7. 【一个小功能】从js判断ie版本,浅谈navigator对象的appName属性

    判断IE版本主要的是获取两个属性,a.当前浏览器名称,b.当前浏览器版本,为此不得不了解navigator对象. 先贴代码 window.onload = function() { var brows ...

  8. 使用final关键字修饰一个引用类型变量时,是引用不能变,还是引用的对象不能变?

    使用final关键字修饰一个引用类型变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的. 测试代码如下: package reviewTest; /** * @ClassName: ...

  9. 什么是不可变对象(immutable object)?Java 中怎么 创建一个不可变对象?

    不可变对象指对象一旦被创建,状态就不能再改变.任何修改都会创建一个新的对象,如 String.Integer 及其它包装类. 详情参见答案,一步一步指导你在 Java中创建一个不可变的类.

随机推荐

  1. SU sugabor命令学习

    不足之处,欢迎批评指正.

  2. js:语言精髓笔记10--闭包

    闭包:  //JS函数式风格中,在内部保存数据和对外无副作用这两个特性主要就是通过闭包实现的: 函数与闭包: 一个函数是一段静态代码,它是一个代码书写时已经编译期,静态概念:闭包是函数在代码运行过程中 ...

  3. POJ3321 Apple Tree(DFS序)

    题目,是对一颗树,单点修改.子树查询.典型的dfs序入门题. DFS序可以将一颗树与子树们表示为一个连续的区间,然后用线段树来维护:感觉算是树链剖分的一种吧,和轻重链剖分不同的是这是对子树进行剖分的. ...

  4. 【BZOJ】1036: [ZJOI2008]树的统计Count(lct/树链剖分)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1036 lct: (ps:为嘛我的那么慢T_T,不知道排到哪了..难道别人都是树剖吗...看来有必要学 ...

  5. 《菊与刀》--[美]鲁思·本尼迪克特(Ruth Benedict)

    <菊与刀>这本书实在是好看. 下面是一些书摘: * 由在美国曾经全力以赴与之战斗的敌人中,日本人的脾气是最琢磨不透的. * “菊”本是日本皇家家微,“刀”是武家文化的象征. * 日本人的格 ...

  6. DWR入门教程

    DWR(Direct Web Remoting)是一个WEB远程调用框架.利用这个框架可以让AJAX开发变得很简单.利用DWR可以在客户端利用JavaScript直接调用服务端的Java方法并返回值给 ...

  7. Struts2_ValueStack,OGNL详解

    一.ValueStack    1.ValueStack是一个接口,在struts2中使用OGNL(Object-Graph Navigation Language)表达式实际上是使用实现了Value ...

  8. hdu Rescue

    因为要求的是最少的时间,很明显的是一个利用优先队列的bfs的题目,题目很一般. #include"iostream" #include"algorithm" # ...

  9. Mui - 全局css

    头部(mh) <header class="mui-bar mui-bar-nav"> <a class="mui-action-back mui-ic ...

  10. top指令

    top - :: up :, user, load average: 0.00, 0.01, 0.05 Tasks: total, running, sleeping, stopped, zombie ...