testus
testus

Reputation: 183

QDir::remove() always causing a crash when called in specific SLOT

Everytime I call QDir::removeRecursively() my application crashes AFTER having removed the folder containing the files correctly. Having done some testing I found out that it depends on how I call the function. This is my code:

Recorder::Recorder(ParentClass *parent): QObject(parent){

     connect(this,SIGNAL(finishedRec(QString,QString)),this,SLOT(finishedRecording(QString,QString)));
}

void Recorder::start(){
    if (!recording){
        recording=true;
        recThread.reset(new std::thread(&Recorder::recordThread, this));
    }
}

void Recorder::stop(){
    recording = false;
    recThread->join(); recThread.reset();
}
void Recorder::recordThread(){
    QString picDir;
    QString filename;
    //....
    while(recording){
        //writing frames to folder
    }    
    emit finishedRec(picDir,filename);    
}

void Recorder::finishedRecording(QString picDir, QString filename){
    QProcess* proc = new QProcess();
    vecProcess.push_back(proc);
    vecString.push_back(picDir);
    proc->start("C:\\ffmpeg.exe", QStringList() <<"-i"<< picDir << "-r"<< "30" << "-vcodec"<< "ffv1" << filename);
    connect(proc,SIGNAL(finished(int)),this,SLOT(finishedProcess()));
}

void Recorder::finishedProcess(){
    for (int i=0; i<vecProcess.size();i++){
        if(vecProcess.at(i)->state()==QProcess::NotRunning){
            delete vecProcess.at(i);
            vecProcess.erase(vecProcess.begin() + i);

            QString folderToRemove=vecString.at(i);
            folderToRemove.chop(12);
            qDebug() << folderToRemove;
            QDir dir(folderToRemove);
            dir.removeRecursively();
            vecString.erase(vecString.begin() + i);

        }
    }
}

Only if I leave dir.removeRecursively() in, my application will always crash. Without it everything works as intended. Even deleting all the files with

QDir dir(path);
dir.setNameFilters(QStringList() << "*.*");
dir.setFilter(QDir::Files);
foreach(QString dirFile, dir.entryList()){
    dir.remove(dirFile);
}

will cause a crash AFTRER all the files were deleted.

I'm running my recordThead as a std::unique_ptr<std::thread>. I did try to run the thread as a QThread but that gave me the exact same result. If dir.removeRecursively() was called the program will crash after finishing the event in finishedProcess()

Calling removeRecursively() in a different event loop works. Why doesn't it work when using it in a SLOT like shown in my example?

Upvotes: 0

Views: 640

Answers (1)

Alexander V
Alexander V

Reputation: 8698

vector erase effectively reduces the container size by the number of elements removed, which are destroyed.

// one suspect
vecProcess.erase(vecProcess.begin() + i);
// another suspect
vecString.erase(vecString.begin() + i);

And you call that in a loop where 'i' gets incremented? Should eventually attempt to erase something beyond the vector size. I would just release entire container if possible after the loop finished or used list. And maybe you don't need to store pointers in those containers but values (?). Storing pointers to objects allocated by you makes you to release the one by one and sometimes, yes, justified but with C++ 11 and move semantics it is not always the case.

Upvotes: 1

Related Questions