使用 c++11 std::thread 获取段错误

Posted

技术标签:

【中文标题】使用 c++11 std::thread 获取段错误【英文标题】:Getting segfault using c++11 std::thread 【发布时间】:2014-01-23 20:47:12 【问题描述】:
static T MultiplyElement(const Matrix& matrixA, const Matrix& matrixB, 
    unsigned M2col, unsigned M1row)

    T sumToReturn = 0;

    for (unsigned iM1colM2row = 0; iM1colM2row < matrixA.m_n; iM1colM2row++)
    
        sumToReturn += 
            matrixA.m_data[M1row][iM1colM2row] * matrixB.m_data[iM1colM2row][M2col];
    

    return sumToReturn;

...

    std::vector<std::thread> threads;
    for(unsigned i = 0; i < outM ; ++i)
    
        for(unsigned j = 0; j < outN; ++j)
        
            threads.push_back(std::thread([&]()
            
                outMatrix.m_data[i][j] = MultiplyElement(matrixA, matrixB, i, j);
            
            ));
        
    
    for(auto& thread : threads)
    
        thread.join();
    

编译: clang++ -std=c++11 -stdlib=libc++ newFile.cpp

我在 MultiplyElement 中遇到了段错误...知道为什么吗?

【问题讨论】:

那么,您是否在调试器中单步执行代码并检查引发错误的代码行?可能是错误的数组索引?这不是“人工调试器”网站。 如果你删除多线程,代码会产生正确的结果——所以这种调试类型不是我想要的。该错误是使用线程的产物,我对 C++11 线程并不精通,所以我正在寻找一些社区帮助:) @user2588666 也许是比赛条件?? 关于竞争条件,我创建了一个变量来锁定线程。我尝试在 outMatrix.m_.... = Multi... 调用之前锁定和解锁,但我仍然得到段错误。 当我放弃 lambda 时,我让它工作了......这一定是问题的根源。 【参考方案1】:

我认为问题在于您的捕获。您正在对所有变量使用引用捕获。您应该按值捕获 ij。尝试 [&amp;, i, j] 作为您的捕获子句。

编辑:您可以查看answer here。你有同样的问题。

【讨论】:

@CantChooseUsernames 它们被循环修改。但即便如此,它们仍然是局部范围的变量。如果线程在一个或两个循环结束后调度,则对 MultiplyElement 的调用将使用未定义的 M2Col 和/或 M1row 值进行 而按值传递将如何改变这一点?它们仍然会被循环修改。无论 OP 是通过值还是通过引用传递它们,在这里都不会有任何区别。采用变量 I 和 J 的函数不会修改它,它将获得与按值传递相同的值。顺便说一句,MultiplyElement 已经将 I 和 J 作为值传递.. @CantChooseUsernames MultiplyElement 是否按值获取它们并不重要,因为thread 不会直接调用该函数。它将通过 lambda 对象执行此操作。 lambda 是问题所在,因为它将通过 ref 保留这些整数。到它被调用时,这些整数可能早已不复存在,并且会读取垃圾。 @Francois,不幸的是我无法测试这个,因为我已经放弃了我的原始代码;但是我几乎可以肯定这会解决我的问题。肯定是从中吸取了教训。谢谢!

以上是关于使用 c++11 std::thread 获取段错误的主要内容,如果未能解决你的问题,请参考以下文章

C++11 的 std::thread 是不是与 POSIX 信号量兼容?

C++ 11 std::thread 循环

混合 C++11 std::thread 和 C 系统线程(即 pthreads)

使用 std::thread 函数 C++11 将指针作为参数传递

std::thread

为线程函数c ++ 11获取多个参数