qtを使用して多数のファイル(通常は小さくはない)をダウンロードする必要があります(速度と表示の進行状況も計算します)。現在、これにはQnetworkAccessManagerを使用していますが、多数の高速ダウンロードでランダムにクラッシュし、最も頻繁にntdll.dll!tan onスタック、グーグルはそれが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
}
更新1:
qt bugtracker にバグを投稿しました。同じ問題のバグもリンクされています。