1

QT 4.8:我的代码中出现了一些段错误和 I/O 可能的错误,我无法弄清楚。从打印语句中,我看到了许多奇怪且不一致的行为,可能表明存在竞争条件。很多时候一切都很完美。有时我在调用 worker 析构函数后立即收到 I/O 错误,表明主连接 deleteLater() 问题。其他时候,如果我尝试在析构函数中删除 audioOutput,它将工作多次,然后在其他尝试的析构函数中间随机给我一个段错误(或 I/O)。我相信我的问题可以归因于两件事,worker cleanup/connect quit()/deletelater() 调用和我在 worker 中的递归循环,它每次都需要创建自己的事件循环,因此可能在之前的调用之前发出完成的信号可以是清理了吗?

具体来说,我的问题是:

什么可能导致 deleteLater() 创建 I/O 可能的错误?

我应该如何删除工人类内部的指针,以便在正确的时间(结束)删除它们......还是 QT 为我处理这个?

桂和.h

QByteArray* qbyte;
QThread* thread;
PlayAudio* audioWorker;

MainWindow::startSound()
{
    QFile soundFile;
    soundFile.setFileName("/home/sounds/sound.wav");
    qbyte = new  QByteArray(soundFile.readAll());
    soundFile.close();
    thread= new QThread;
    audioWorker= new PlayAudio(qbyte, 5);
    audioWorker->moveToThread(thread);
    connect(thread, SIGNAL(started()), audioWorker, SLOT(play()));
    connect(audioWorker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(audioWorker, SIGNAL(finished()), audioWorker,SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), this, SLOT(donePlaying()));
}
MainWindow::donePlaying()
{
    //do stuff
}

工人阶级和.h

QByteArray qbyte;
int numOfPlays;
int numOfPlaysRun;
bool quit = false;
QBuffer *qbuff;
QAudioFormat format;
QAudioOutput *audioOutput;

PlayAudio::PlayAudio(QByteArray *qbyte_, int num)
{
    qbyte=*qbyte_;
    numOfPlays=num;
    qbuff=new QBuffer();
    qbuff->setData(qbyte);
    qbuff->open(QIODevice::ReadOnly); 
       //set format
    audioOutput  = new QAudioOutput(format,this);  
    connect(audioOutput,SIGNAL(stateChanged(QAudio::State)),
                           SLOT(finishedPlaying(QAudio::State)));
}

void PlayAudio::::play()
{
    if (!quit)
    {
        audioOutput->start(qbuff);
        QEventLoop loop;
        do {
            loop.exec();            
        } while(!quit);
    }
}

 void PlayAudio::finishedPlaying(QAudio::State state)
{
    if (state == QAudio::IdleState)
    {
        if (numOfPlaysRun< numOfPlays && !quit)
        {
            numOfPlaysRun++;
            play();
        }
        else
        {
            //should i ever stop loop myself? or is that done from main?
            //quit=true;
            emit finished();
        }
    }
}
PlayAudio:: ~PlayAudio()
{
    // still have  qbuff and audioOutput to delete. If i do here i sometimes            
    //get segment faults or IO error.
}

更新:

仍然存在间歇性问题,但注释掉以下行有助于清除其中一些问题并结合设置 quit=true。

connect(audioWorker, SIGNAL(finished()), audioWorker,SLOT(deleteLater()));

但这可能会导致内存泄漏?


更新 2:

我开始认为我在这里自言自语,但我想我明白了。这似乎是一个时间问题,因为线程在工作人员实际完成之前返回完成(),因为一旦工作人员发出完成(),退出()信号就会关闭开环。因此,我现在为每个关闭的循环从 worker 发出一个自定义信号,并在 main.js 中跟踪它。一旦我收到我期望的内容,我就会释放 wait() 并删除线程 THEN 然后是 worker。不确定这是否正确,但它似乎正在工作。对我来说似乎很骇人听闻,但IMO线程不应该在工人完成之前返回完成,那时似乎毫无意义。但是哦,好吧。

4

0 回答 0