2

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 にバグを投稿しました。同じ問題のバグもリンクされています。

https://bugreports.qt-project.org/browse/QTBUG-25​​514

4

0 に答える 0