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线程不应该在工人完成之前返回完成,那时似乎毫无意义。但是哦,好吧。