简体   繁体   中英

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:

  1. Iterator or a Sequence, in my case I am using a QList .
  2. 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)

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?

Honestly, some parts of your question are not clear for me. However, please take into account the followings (although you may have considered some or all of them):

  1. the functor is highly recommended to be a static function. From your code, it seems that you may have not declared the static function properly. Please put the following in your MainWindow.h:
static void mapSumToQString(QPair<int, int> pair);

and modify the implementation as follows:

// MapFunctor
void MainWindow::mapSumToQString(QPair<int, int> pair)
{
    j++;
    qDebug() << "Execute " << j << " = " << QString::number(pair.first, pair.second);;
}
  1. mapSumToQString is static, hence you cannot use non-static members of the MainWindow inside it. Hence, the i must be static as well.
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
  1. Modify MainWindow.cpp as follows:
    // counter variable stored in MainWindow
    j = 0;

    QFuture<void> future;
    future = QtConcurrent::map(intPairList, mapSumToQString);
    future.waitForFinished();
  1. One thing that I cannot understand is that you are converting an integer to a string with a random base?!
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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM