c++ - Using QtConcurrent::map() function on QList yields segmentation fault
问题描述
I am familiarizing myself with QtConcurrent library. I have a UI (MainWindow
) where I run my functions to simulate a real world example of multithreading.
The QtConcurrent::map() function I am using requires some:
- Iterator or a Sequence, in my case I am using a QList.
- Further, it requires a MapFunctor (which supports lambdas*) but for this purpose, I am choosing to stick to a static method for testing.
What I have tried
I attempted using both map() functions (the first is left uncommented)
- QtConcurrent::map(Sequence &sequence, MapFunctor function
- QtConcurrent::map(Iterator begin, Iterator end, MapFunctor function)
I tried searching for a Sequence and a MapFunctor, but I could only find it in templates which did not help alot, thus I had to try and use my intuition to make sense of it.
The Code:
Somewhere inside my MainWindow.cpp
// counter variable stored in MainWindow
int i = 0;
// MapFunctor
void mapSumToQString(QPair<int, int> pair)
{
i++;
qDebug() << "Execute " << i << " = " << QString::number(pair.first, pair.second);;
}
and the code to start it all
// UI class decl
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create list of integers to perform map function on (here I don't write back to the original sequence i.e. list)
QList<QPair<int, int>> intPairList = QList<QPair<int, int>>();
for (int i = 0; i < 1000; i++) {
int i1 = qrand();
int i2 = qrand();
intPairList.append(QPair<int, int>(i1, i2));
}
QFuture<void> future;
future = QtConcurrent::map(intPairList, mapSumToQString);
// future = QtConcurrent::map(intPairList.begin(), intPairList.end(), mapSumToQString);
}
Problem:
Running this snippet of code results in a SEGV here
namespace QtConcurrent {
// map kernel, works with both parallel-for and parallel-while
template <typename Iterator, typename MapFunctor>
class MapKernel : public IterateKernel<Iterator, void>
{
MapFunctor map;
public:
typedef void ReturnType;
MapKernel(Iterator begin, Iterator end, MapFunctor _map)
: IterateKernel<Iterator, void>(begin, end), map(_map)
{ }
bool runIteration(Iterator it, int, void *) override
{
map(*it); <--------SEGV line
return false;
}
//...
}
Stacktrace (copied from debugger)
1 QtConcurrent::MapKernel<QList<QPair<int, int>>::iterator, QtConcurrent::FunctionWrapper1<void, QPair<int, int>>>::runIteration qtconcurrentmapkernel.h 68 0x404ee8
2 QtConcurrent::MapKernel<QList<QPair<int, int>>::iterator, QtConcurrent::FunctionWrapper1<void, QPair<int, int>>>::runIterations qtconcurrentmapkernel.h 77 0x404f82
3 QtConcurrent::IterateKernel<QList<QPair<int, int>>::iterator, void>::forThreadFunction qtconcurrentiteratekernel.h 255 0x40466e
4 QtConcurrent::IterateKernel<QList<QPair<int, int>>::iterator, void>::threadFunction qtconcurrentiteratekernel.h 217 0x404486
5 QtConcurrent::ThreadEngineBase::run qtconcurrentthreadengine.cpp 302 0x6d881973
6 QThreadPoolThread::run qthreadpool.cpp 99 0x111b36a
7 QThreadPrivate::start(void *) *4 qthread_win.cpp 403 0x11163eb
8 KERNEL32!BaseThreadInitThunk 0x74d56359
9 ntdll!RtlGetAppContainerNamedObjectPath 0x77467c24
10 ntdll!RtlGetAppContainerNamedObjectPath 0x77467bf4
11 ??
For the record, there is another question related to this, but most certainly does not provide a usable solution.
Why do I get this SEGV, what is causing this access violation?
解决方案
老实说,您的问题的某些部分对我来说并不清楚。但是,请考虑以下几点(尽管您可能已经考虑了部分或全部):
- 强烈建议仿函数是静态函数。从您的代码看来,您可能没有正确声明静态函数。请在 MainWindow.h 中添加以下内容:
static void mapSumToQString(QPair<int, int> pair);
并修改实现如下:
// MapFunctor
void MainWindow::mapSumToQString(QPair<int, int> pair)
{
j++;
qDebug() << "Execute " << j << " = " << QString::number(pair.first, pair.second);;
}
mapSumToQString
是静态的,因此您不能在MainWindow
其中使用非静态成员。因此,i
也必须是静态的。
static int j; //in MainWindow.h ---> I changed i to j to make it differ from your For loop variable
int MainWindow::j = 0;//in MainWindow.cpp ----> static variables have to be initialized
- 修改 MainWindow.cpp 如下:
// counter variable stored in MainWindow
j = 0;
QFuture<void> future;
future = QtConcurrent::map(intPairList, mapSumToQString);
future.waitForFinished();
- 我无法理解的一件事是您正在将整数转换为具有随机基数的字符串?!
qDebug() << "Execute " << j << " = " << QString::number(pair.first, pair.second);
//Herein, pair.second is random, and hence QString::number's second input (base) is always a random number. Do you really want it?
推荐阅读
- sql - 将数据从表单附加到列
- azure - 为什么当 HasMoreResults 为 True 时 CosmosDB FeedResponse 不包含结果
- angular - 捕获从服务到组件的响应?
- java - 网络代码执行后的 Java UI 白屏
- java - 在不放入参数列表的情况下访问 Spring WebDataBinder 的 BindingResult
- c++ - 正确读取数据但写入错误
- corda - 生成包含事务命令的分类帐更改事件的最佳方法是什么?
- aws-lambda - Lambda 授权方不尊重资源
- spring-cloud-feign - openfeign 和 feign 的区别
- python - Pandas:如何使用其他数据框的列替换数据框中的值