使用 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】:我认为问题在于您的捕获。您正在对所有变量使用引用捕获。您应该按值捕获 i
和 j
。尝试 [&, 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 系统线程(即 pthreads)