问题描述
在使用 std :: thread 测试某些功能时,一个朋友遇到了GCC的问题,我们认为这是值得问的,如果这是一个GCC错误,或者有错误使用这个代码(代码打印(例如)7 8 9 10 1 2 3,但我们希望打印[1,10]中的每个整数):
While testing some functionality with std::thread, a friend encountered a problem with GCC and we thought it's worth asking if this is a GCC bug or perhaps there's something wrong with this code (the code prints (for example) "7 8 9 10 1 2 3", but we expect every integer in [1,10] to be printed):
#include <algorithm> #include <iostream> #include <iterator> #include <thread> int main() { int arr[10]; std::iota(std::begin(arr), std::end(arr), 1); using itr_t = decltype(std::begin(arr)); // the function that will display each element auto f = [] (itr_t first, itr_t last) { while (first != last) std::cout<<*(first++)<<' ';}; // we have 3 threads so we need to figure out the ranges for each thread to show int increment = std::distance(std::begin(arr), std::end(arr)) / 3; auto first = std::begin(arr); auto to = first + increment; auto last = std::end(arr); std::thread threads[3] = { std::thread{f, first, to}, std::thread{f, (first = to), (to += increment)}, std::thread{f, (first = to), last} // go to last here to account for odd array sizes }; for (auto&& t : threads) t.join(); }
以下替代代码适用:
int main() { std::array<int, 10> a; std::iota(a.begin(), a.end(), 1); using iter_t = std::array<int, 10>::iterator; auto dist = std::distance( a.begin(), a.end() )/3; auto first = a.begin(), to = first + dist, last = a.end(); std::function<void(iter_t, iter_t)> f = []( iter_t first, iter_t last ) { while ( first != last ) { std::cout << *(first++) << ' '; } }; std::thread threads[] { std::thread { f, first, to }, std::thread { f, to, to + dist }, std::thread { f, to + dist, last } }; std::for_each( std::begin(threads),std::end(threads), std::mem_fn(&std::thread::join)); return 0; }
我们认为它可能与函数的arity它只是方式 std :: thread 应该在复制非 - std :: ref -qualified参数时工作。然后我们用Clang测试第一个代码,它工作(因此开始怀疑一个GCC错误)。
We thought maybe its got something to do with the unsequenced evaluation of function's arity or its just the way std::thread is supposed to work when copying non-std::ref-qualified arguments. We then tested the first code with Clang and it works (and so started to suspect a GCC bug).
使用的编译器:GCC 4.7,Clang 3.2.1
Compiler used: GCC 4.7, Clang 3.2.1
EDIT: GCC代码为第一个版本的代码提供了错误的输出,但是第二个版本提供了正确的输出。
The GCC code gives the wrong output with the first version of the code, but with the second version it gives the correct output.
推荐答案
从这个修改的程序:
#include <algorithm> #include <iostream> #include <iterator> #include <thread> #include <sstream> int main() { int arr[10]; std::iota(std::begin(arr), std::end(arr), 1); using itr_t = decltype(std::begin(arr)); // the function that will display each element auto f = [] (itr_t first, itr_t last) { std::stringstream ss; ss << "**Pointer:" << first << " | " << last << std::endl; std::cout << ss.str(); while (first != last) std::cout<<*(first++)<<' ';}; // we have 3 threads so we need to figure out the ranges for each thread to show int increment = std::distance(std::begin(arr), std::end(arr)) / 3; auto first = std::begin(arr); auto to = first + increment; auto last = std::end(arr); std::thread threads[3] = { std::thread{f, first, to}, #ifndef FIX std::thread{f, (first = to), (to += increment)}, std::thread{f, (first = to), last} // go to last here to account for odd array sizes #else std::thread{f, to, to+increment}, std::thread{f, to+increment, last} // go to last here to account for odd array sizes #endif }; for (auto&& t : threads) { t.join(); } }
我添加第一个和最后 lambda函数 f 的指针,并找到这个有趣的结果 FIX 未定义):
I add the prints of the first and last pointer for lambda function f, and find this interesting results (when FIX is undefined):
**Pointer:0x28abd8 | 0x28abe4 1 2 3 **Pointer:0x28abf0 | 0x28abf0 **Pointer:0x28abf0 | 0x28ac00 7 8 9 10
然后我为 #ELSE 大小写为 #ifndef FIX 。它工作得很好。
Then I add some code for the #ELSE case for the #ifndef FIX. It works well.
- 更新:这个结论,下面的原始帖子是错误的。我的错。请参阅下面的Josh的注释 -
strong> --- Update:corrected ---
--- Update: corrected ---
因此,上述调试打印结果表明GCC4.8.2(我的版本)
仍然是buggy(不是说GCC4.7),但是GCC 4.9.2修复了这个bug,如Maxim Yegorushkin报告的
(见上面的注释)。
Thus the above debug printing results suggest that GCC4.8.2 (my version)is still buggy (not to say GCC4.7), but GCC 4.9.2 fixes this bug, asreported by Maxim Yegorushkin (see comment above).
这篇关于(优化?)有关GCC std :: thread的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!