这个小程序有内存(或其他资源)泄漏吗?

AAA20090987 2012-08-17 09:33:01
先上代码:

#include <QtCore>  
#include <QtNetwork>

//多线程下载的线程数
const int PointCount = 100;
//目标文件的地址(千千静听的下载地址,我用来做实验的)
const QString strUrl = "http://ttplayer.qianqian.com/otherdown/alladin/ttpsetup_5713.exe";

//用于下载文件(或文件的一部分)
class Download : public QObject
{
Q_OBJECT
private:
QNetworkAccessManager m_Qnam;
QNetworkReply *m_Reply;
QFile *m_File;

const int m_Index;
qint64 m_HaveDoneBytes;
qint64 m_StartPoint;
qint64 m_EndPoint;

public:
Download(int index, QObject *parent = 0);
void StartDownload(const QUrl &url, QFile *file,
qint64 startPoint=0, qint64 endPoint=-1);
signals:
void DownloadFinished();

public slots:
void FinishedSlot();
void HttpReadyRead();
};

//用于管理文件的下载
class DownloadControl : public QObject
{
Q_OBJECT
private:
int m_DownloadCount;
int m_FinishedNum;
int m_FileSize;
QUrl m_Url;
QFile *m_File;
public:
DownloadControl(QObject *parent = 0);
void StartFileDownload(const QString &url, int count);
qint64 GetFileSize(QUrl url);
signals:
void FileDownloadFinished();
private slots:
void SubPartFinished();
};

Download::Download(int index, QObject *parent)
: QObject(parent), m_Index(index)
{
m_HaveDoneBytes = 0;
m_StartPoint = 0;
m_EndPoint = 0;
m_File = NULL;
}

void Download::StartDownload(const QUrl &url,
QFile *file,
qint64 startPoint/* =0 */,
qint64 endPoint/* =-1 */)
{
if( NULL == file )
return;

m_HaveDoneBytes = 0;
m_StartPoint = startPoint;
m_EndPoint = endPoint;
m_File = file;

//根据HTTP协议,写入RANGE头部,说明请求文件的范围
QNetworkRequest qheader;
qheader.setUrl(url);
QString range;
range.sprintf("Bytes=%lld-%lld", m_StartPoint, m_EndPoint);
qheader.setRawHeader("Range", range.toAscii());

//开始下载
qDebug() << "Part " << m_Index << " start download";
m_Reply = m_Qnam.get(QNetworkRequest(qheader));
connect(m_Reply, SIGNAL(finished()),
this, SLOT(FinishedSlot()));
connect(m_Reply, SIGNAL(readyRead()),
this, SLOT(HttpReadyRead()));
}

//下载结束
void Download::FinishedSlot()
{
m_File->flush();
m_Reply->deleteLater();
m_Reply = 0;
m_File = 0;
qDebug() << "Part " << m_Index << " download finished";
emit DownloadFinished();
}

void Download::HttpReadyRead()
{
if ( !m_File )
return;

//将读到的信息写入文件
QByteArray buffer = m_Reply->readAll();
m_File->seek( m_StartPoint + m_HaveDoneBytes );
m_File->write(buffer);
m_HaveDoneBytes += buffer.size();
}

//用阻塞的方式获取下载文件的长度
qint64 DownloadControl::GetFileSize(QUrl url)
{
QNetworkAccessManager manager;
qDebug() << "Getting the file size...";
QEventLoop loop;
//发出请求,获取目标地址的头部信息
QNetworkReply *reply = manager.head(QNetworkRequest(url));
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()), Qt::DirectConnection);
loop.exec();
QVariant var = reply->header(QNetworkRequest::ContentLengthHeader);
reply->deleteLater();
qint64 size = var.toLongLong();
qDebug() << "The file size is: " << size;
return size;
}

DownloadControl::DownloadControl(QObject *parent)
: QObject(parent)
{
m_DownloadCount = 0;
m_FinishedNum = 0;
m_FileSize = 0;
m_File = new QFile;
}

void DownloadControl::StartFileDownload(const QString &url, int count)
{
m_DownloadCount = count;
m_FinishedNum = 0;
m_Url = QUrl(url);
m_FileSize = GetFileSize(m_Url);
//先获得文件的名字
QFileInfo fileInfo(m_Url.path());
QString fileName = fileInfo.fileName();
if (fileName.isEmpty())
fileName = "index.html";

m_File->setFileName(fileName);
//打开文件
m_File->open(QIODevice::WriteOnly);
Download *tempDownload;

//将文件分成PointCount段,用异步的方式下载
qDebug() << "Start download file from " << strUrl;
for(int i=0; i<m_DownloadCount; i++)
{
//先算出每段的开头和结尾(HTTP协议所需要的信息)
int start = m_FileSize * i / m_DownloadCount;
int end = m_FileSize * (i+1) / m_DownloadCount;
if( i != 0 )
start--;

//分段下载该文件
tempDownload = new Download(i+1, this);
connect(tempDownload, SIGNAL(DownloadFinished()),
this, SLOT(SubPartFinished()));
connect(tempDownload, SIGNAL(DownloadFinished()),
tempDownload, SLOT(deleteLater()));
tempDownload->StartDownload(m_Url, m_File, start, end);
}
}

void DownloadControl::SubPartFinished()
{
m_FinishedNum++;
//如果完成数等于文件段数,则说明文件下载完毕,关闭文件,发生信号
if( m_FinishedNum == m_DownloadCount )
{
m_File->close();
emit FileDownloadFinished();
qDebug() << "Download finished";
}
}

#include "main.moc"

int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
//用阻塞的方式下载文件,完成后退出
DownloadControl *control = new DownloadControl;
QEventLoop loop;
QObject::connect(control, SIGNAL(FileDownloadFinished()),
&loop, SLOT(quit()));
control->StartFileDownload(strUrl, PointCount);
loop.exec();
control->deleteLater();
return 0;
}



以上是我写的一个多线程下载的例子,本来是发表在我的博客上的,
博客地址:http://blog.csdn.net/aaa20090987/article/details/7223026

有几个问题:
1:有人评论说我下载完成后没释放资源(句柄),是这样的吗?应该怎么改正?
2:如果我的下载线程数变成100以上(const int PointCount = 100;),那么下载将无法完成,这是什么原因呢?

PS:为了保持DEMO的简单,我没有对网络中的错误进行处理。
...全文
145 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
sno_guo 2012-08-19
  • 打赏
  • 举报
回复
演示了一下,干嘛没有什么问题啊,呵呵
dext 2012-08-17
  • 打赏
  • 举报
回复
既然涉及到多线程,那么不加互斥量的访问
m_FinishedNum++;
本生就是一个问题。

16,235

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧