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