首页 > 解决方案 > 具有成员函数的实例化对象,在将其成员函数传递给新线程时表现为未实例化

问题描述

我正在尝试并行化数组计算,为此我构建了一个具有 Worker(内部)类的 Shader(外部)类。外部类接收一个数组和它的大小,然后继续在新的 Workers 实例之间划分它。它创建一个工人向量,然后创建一个分配了工作函数的线程向量。不幸的是,该应用程序因 seg 而崩溃。错误并使用调试器我已经确认某些对象没有实例化(而有些对象实际上是实例化的)并且缺少所需的数据。由于实例化不是并行完成的,因此不应该存在任何类型的竞争条件。

我正在使用 mingw_64 作为编译器。其他库是<iostream>,<c++/4.8.3/sstream>,<math.h>,<SDL.h>,<SDL_image.h>,<thread>,<vector>.

Outer类的主要功能:

    void BlurShader::render()
    {
        int threadsNum;
        for (threadsNum = 6; threadsNum > 1; threadsNum--)
        {
            if (height % threadsNum == 0) break;
        }
        int heightStep = height / threadsNum;
        auto *workerObjects = new vector<Worker*>;
        auto *workerThreads = new vector<thread *>;

    // Instantiating workers:

        for (int i = 0; i < threadsNum; i++)
        {
            workerObjects->push_back(
        new Worker(this->original, this->palette, this->width, this->height,
            i * heightStep,((i + 1) * heightStep) - 1));
        }

        /* As you can see a lot of information is streamed into the worker,     
           and it is relying on it. Then in a second for loop I create 
           threads: */

        for (int i = 0; i < threadsNum; i++)
        {
            workerThreads->push_back(new thread([&]() 
            {
                (*workerObjects)[i]->threadProcess(); 
            }));
        }

        // Then the main thread waits for threads to finish:
        for (int j = 0; j < threadsNum; j++)
        {
            (*workerThreads)[j]->join();
            delete (*workerThreads)[j];
        }
        // Cleanup

        for(int i=0;i<threadsNum;i++)
        {
            delete (*workerObjects)[i];
        }
        delete workerObjects;
        delete workerThreads;
        memcpy(original, palette, height * width * size);
    }

期待您的建议。如果你发现我用错了线程,我很乐意听。我只学了一个星期的 C++,所以一切顺利。

标签: c++

解决方案


问题在于 lambda 捕获的方式i

for (int i = 0; i < threadsNum; i++)
        {
            workerThreads->push_back(new thread([&]() // [1]
            {
                (*workerObjects)[i]->threadProcess(); 
            }));
        }

i通过引用捕获,但您不知道何时调用线程的主体,即闭包,因此可能在读取正确值之前i(通过for循环)进行了修改。i

通过i副本:

for (int i = 0; i < threadsNum; i++)
        {
            workerThreads->push_back(new thread([&,i]() // pass i by copy 
            {
                (*workerObjects)[i]->threadProcess(); 
            }));
        }

推荐阅读