背景
在我的 Qt5.3 应用程序中,我处理了几个耗时的过程(统计计算)。为了能够在运行一个或多个计算时使用应用程序,我创建了一个名为ProgressManager的类。此管理器注册从抽象类IRunnable继承并实现纯虚拟方法run的计算对象。
每次启动一个新的耗时操作时,都会在与其进度条相连的ProgressManager中注册,并通过以下函数启动:
void ProgressManager::runProgress(const QVariant &id, const QVariant ¶m) {
// If progress is not present, exit
if (!progs.contains(id)) {
return;
}
// If progress is not runnable, exit
IRunnable* runnable = dynamic_cast<IRunnable*>(progs.value(id));
if (!runnable) {
return;
}
// Create future watcher
QFutureWatcher<QVariant>* watcher = new QFutureWatcher<QVariant>();
connect(watcher, SIGNAL(finished()), this, SLOT(handleFinished()));
// Register running progress
running.insert(watcher, id);
// Paralelize runnable progress
QFuture<QVariant> future = QtConcurrent::run(runnable, &IRunnable::run, param);
watcher->setFuture(future);
}
并行进程完成后,应调用以下函数:
void ProgressManager::handleFinished() {
// Retrieves sender watcher
QObject* s = this->sender();
QFutureWatcher<QVariant>* w = dynamic_cast<QFutureWatcher<QVariant>*>(s);
// Retrieve ID of running progress and delete watcher
QVariant id = running.value(w);
running.remove(w);
delete w;
// Emit progress has finished
emit finished(id);
}
问题
一切都运行顺利,直到并行化过程结束。然后在调用完成信号和句柄完成槽之前,应用程序每次都因分段错误而崩溃。
崩溃报告在文件 qfutureinterface.h 的第 211 行的函数reportResults中,其中函数是reportResultsReady调用:
194 template <typename T>
195 inline void QFutureInterface<T>::reportResult(const T *result, int index)
196 {
197 QMutexLocker locker(mutex());
198 if (this->queryState(Canceled) || this->queryState(Finished)) {
199 return;
200 }
201
202 QtPrivate::ResultStore<T> &store = resultStore();
203
204
205 if (store.filterMode()) {
206 const int resultCountBefore = store.count();
207 store.addResult(index, result);
208 this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
209 } else {
210 const int insertIndex = store.addResult(index, result);
211 this->reportResultsReady(insertIndex, insertIndex + 1);
212 }
213 }