我需要用qt(也计算速度和显示进度)下载大量文件(通常不是很小),目前我使用QnetworkAccessManager,但是在大量快速下载时它会随机崩溃,最常见的是ntdll.dll !在堆栈上晒黑,google说这是来自win api的堆分配,我不在这个代码部分做任何手动内存管理所以我认为我不能通过我的代码做内存损坏,我也试图不删除qnetworkreply对象哪个也没有解决崩溃问题,这里是代码部分:
请求:
QNetworkReply *r = qnm.get(req);
connect(r, SIGNAL(downloadProgress(qint64,qint64)), SLOT(game_s_file_download_progress(qint64,qint64)), Qt::QueuedConnection);
connect(r, SIGNAL(finished()), &conn_timer, SLOT(stop()), Qt::QueuedConnection);
connect(r, SIGNAL(finished()), SLOT(game_sz_file_request_finished()), Qt::QueuedConnection);
connect(r, SIGNAL(downloadProgress(qint64,qint64)), &conn_timer, SLOT(start()), Qt::QueuedConnection);
connect(r, SIGNAL(downloadProgress(qint64,qint64)), spd_calc_obj, SLOT(handle_new_data(qint64,qint64)), Qt::QueuedConnection);
conn_timer_obj *ct = new conn_timer_obj(0, r);
connect(r, SIGNAL(finished()), ct, SLOT(deleteLater()), Qt::QueuedConnection);
connect(&conn_timer, SIGNAL(timeout()), ct, SLOT(abort()), Qt::QueuedConnection);
connect(&conn_timer, SIGNAL(timeout()), &conn_timer, SLOT(stop()));
conn_timer.start();
(qnm是QnetworkAccessManager)
处理数据:
lists_mutex.lock();
QNetworkReply *current_file = qobject_cast<QNetworkReply*>(sender());
assert(current_file != NULL);
#ifdef DEBUG
try{
#endif
if(current_file->error() == QNetworkReply::NoError)
{
if(!updated_size_c_f)
updated_size_c_f = updated_size_c_f_completed + bytesTotal;
QString filename = cfg->game_path();
if(!updated_g_s_list_http.empty())
{
filename += QString::fromUtf8(updated_g_s_list_http.begin()->name.c_str());
if(filename.indexOf("/l10n/") != -1)
{
int p1 = 0, p2 = 0;
p1 = filename.indexOf("/l10n/");
p1+= strlen("/l10n/");
p2 = filename.indexOf("/", p1+1);
filename.remove(p1, p2-p1);
}
}
else
filename += QString("/upd/" + QString::fromUtf8(updated_g_f_list.begin()->path.c_str()));
updated_size_completed_mutex.lock();
updated_size_completed += current_file->bytesAvailable();
updated_size_c_f_completed += current_file->bytesAvailable();
emit set_progress2(((double)updated_size_completed/(double)updated_size)*100.0);
QFile file(filename + ".upd_part");
if(file.open(QIODevice::WriteOnly | QIODevice::Append))
{
file.write(current_file->readAll());
file.close();
}
else
current_file->abort();
if(!partial_pak_downloading)
emit set_progress(((double)updated_size_c_f_completed/(double)updated_size_c_f)*100.0);
updated_size_completed_mutex.unlock();
}
else
{
#ifdef DEBUG
cfg->log()<<current_file->errorString();
#endif
current_file->abort();
}
#ifdef DEBUG
}
catch(...)
{
cfg->log()<<"exception in game_s_file_download_progres: ";
lists_mutex.unlock();
}
#endif
lists_mutex.unlock();
}
并完成信号:
QNetworkReply *current_file = qobject_cast<QNetworkReply*>(sender());
assert(current_file != NULL);
lists_mutex.lock();
current_file->disconnect();
conn_timer.disconnect();
QString filename = cfg->game_path();
#ifdef DEBUG
try{
#endif
if(!updated_g_s_list_http.empty())
{
#ifdef DEBUG
upd_stats.incr_d_h();
#endif
filename += QString::fromUtf8(updated_g_s_list_http.begin()->name.c_str());
if(filename.indexOf("/l10n/") != -1)
{
int p1 = 0, p2 = 0;
p1 = filename.indexOf("/l10n/");
p1+= strlen("/l10n/");
p2 = filename.indexOf("/", p1+1);
filename.remove(p1, p2-p1);
}
}
else
{
assert(!updated_g_f_list.empty());
filename += QString("/upd/" + QString::fromUtf8(updated_g_f_list.begin()->path.c_str()));
}
#ifdef DEBUG
}
catch(...)
{
cfg->log()<<"exception in game_sz_file_request_finished part 1: ";
}
#endif
if(current_file->error() == QNetworkReply::NoError)
{
#ifdef DEBUG
try{
#endif
fail_dl_count = 0;
int have_bytes = current_file->bytesAvailable();
if(have_bytes)
{
updated_size_completed_mutex.lock();
updated_size_completed += have_bytes;
emit set_progress2(((double)updated_size_completed/(double)updated_size)*100.0);
updated_size_completed_mutex.unlock();
QFile file(filename + ".upd_part");
if(file.open(QIODevice::WriteOnly | QIODevice::Append))
{
file.write(current_file->readAll());
file.close();
}
else
;//TODO: handle error
}
UPDATE1:
我已经在qt bugtracker上发布了bug,它也有相同问题的链接错误: