QВопросы Авария после 2058 года - PullRequest
0 голосов
/ 12 октября 2009

Следующий код потока запускается 2058 раз, после этого происходит сбой. Может кто-нибудь помочь мне понять, почему? Идея программы состоит в том, чтобы создать некоторый класс в основном потоке, передать его в рабочий поток, поток заполняет необходимые данные и передавать данные обратно в основной поток. Этот пример вылетает после запуска 2058 года, однако он должен работать неопределенно долго. Я запускал его 20 раз, всегда один и тот же номер. В версии сокращенных вызовов qWarning () (печатать простую строку каждые 100 запусков) поток выполняется 3000 раз. Поэтому я думаю, что это не зависит от количества вызовов qWarning (). И почему адрес указателя для SharedData * d всегда одинаков?

main.cpp

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TestThread* thread = new TestThread();

    MainWindow w(thread);
    w.show();

    delete thread;
    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QThread>
#include <QHash>

class SharedData
{
    public:
        SharedData();
        QString var;
        QHash<QString, QString> hash;
};

class TestThread : public QThread
{
    Q_OBJECT

    public:
        TestThread(QObject *parent = 0);
        void doWork(SharedData* _data);
        void doCrash(QHash<QString, QString>* hash);
    signals:
        void completed(SharedData* d);
    private:
        SharedData* data;
    protected:
        void run();
};

namespace Ui
{
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(TestThread* t, QWidget *parent = 0);
    ~MainWindow();
    void runThread();
public slots:
    void jobDone(SharedData* req);

private:
    Ui::MainWindow *ui;
    TestThread* t;
    int runcount;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug.h>

TestThread::TestThread(QObject *parent) : QThread(parent)
{
}

void TestThread::run()
{
    qWarning() << "Thread running";
    data->var = "hello";
    doCrash(&data->hash);
    emit completed(data);
}

void TestThread::doWork(SharedData* _data)
{
    data = _data;
    qWarning() << "Attempting to start";
    if(!isRunning())
    {
        run();
    }
    else
    {
        qWarning() << "Oops. Already running";
    }
}

void TestThread::doCrash(QHash<QString, QString>* hash)
{
    hash->insert("test", "123");

    /*
    QHashIterator<QString, QString> i(*hash);
    while (i.hasNext()) {
       i.next();
       qWarning() << i.key() + ":" + i.value();
    }
    */
}

SharedData::SharedData()
{
}

void MainWindow::jobDone(SharedData* req)
{
    qWarning() << "RETURNED";
    qWarning() << "var: " << req->var << " addr: " << &req->var;
    qWarning() << "cnt: " << req->hash.count() << " addr: " << &req->hash;

    QHashIterator<QString, QString> i(req->hash);

    while (i.hasNext()) {
       i.next();
        qWarning() << i.key() + ":" + i.value();
    }

    delete req;
    runThread();
}

MainWindow::MainWindow(TestThread* _t, QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    t = _t;
    connect(t, SIGNAL(completed(SharedData*)), this, SLOT(jobDone(SharedData*)));
    runcount = 0;
    runThread();
}

void MainWindow::runThread()
{
    SharedData* d = new SharedData();
    d->var = "test";

    runcount++;
    qWarning() << "Run count: " << runcount;

    qWarning() << "CREATING THREAD";
    qWarning() << "var: " << d->var << " addr: " << &d->var;
    qWarning() << "cnt: " << d->hash.count() << " addr: " << &d->hash;

    t->doWork(d);
}

MainWindow::~MainWindow()
{
    delete ui;
}

Ответы [ 2 ]

2 голосов
/ 12 октября 2009

Как указала vnm, причиной сбоя, скорее всего, является инструкция delete thread; в main.cpp: когда вы вызываете w.show (), он сразу же возвращается, и запускается вызов exec (). цикл и блок событий, но к тому времени уже слишком поздно, поскольку поток уже был удален.

Я бы объявил поток как элемент без указателя в главном окне, а не передавал его как параметр, таким образом, компилятор выполнит за вас очистку и инициализацию. Еще более простым решением было бы использовать QtConcurrent :: run . Делая это, вы устраняете весь явный код протектора, но все же получаете преимущества многопоточности.

2 голосов
/ 12 октября 2009

Вы не должны удалять свой экземпляр TestThread в main.cpp (закомментируйте строку «delete thread;»)!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...