我正在尝试使用std :: thread和C ++ 11,我遇到了奇怪的行为。 请查看以下代码:
#include <cstdlib>
#include <thread>
#include <vector>
#include <iostream>
void thread_sum_up(const size_t n, size_t& count) {
size_t i;
for (i = 0; i < n; ++i);
count = i;
}
class A {
public:
A(const size_t x) : x_(x) {}
size_t sum_up(const size_t num_threads) const {
size_t i;
std::vector<std::thread> threads;
std::vector<size_t> data_vector;
for (i = 0; i < num_threads; ++i) {
data_vector.push_back(0);
threads.push_back(std::thread(thread_sum_up, x_, std::ref(data_vector[i])));
}
std::cout << "Threads started ...\n";
for (i = 0; i < num_threads; ++i)
threads[i].join();
size_t sum = 0;
for (i = 0; i < num_threads; ++i)
sum += data_vector[i];
return sum;
}
private:
const size_t x_;
};
int main(int argc, char* argv[]) {
const size_t x = atoi(argv[1]);
const size_t num_threads = atoi(argv[2]);
A a(x);
std::cout << a.sum_up(num_threads) << std::endl;
return 0;
}
这里的主要思想是我想指定一些执行独立计算的线程(在这种情况下,简单的增量)。 完成所有线程后,应合并结果以获得整体结果。
只是为了澄清:这仅用于测试目的,以便让我了解如何 C ++ 11线程可以工作。
但是,使用命令
编译此代码时g++ -o threads threads.cpp -pthread -O0 -std=c++0x
在Ubuntu框中,当我执行生成的二进制文件时,我会遇到非常奇怪的行为。 例如:
$ ./threads 1000 4
Threads started ...
Segmentation fault (core dumped)
(应该产生输出:4000)
$ ./threads 100000 4
Threads started ...
200000
(应该产生输出:400000)
有人知道这里发生了什么吗?
提前谢谢!
答案 0 :(得分:2)
您的代码有很多问题(甚至可以查看thread_sum_up
大约2-3个错误)但是通过浏览代码我发现的主要错误是:
data_vector.push_back(0);
threads.push_back(std::thread(thread_sum_up, x_, std::ref(data_vector[i])));
当您push_back
进入向量时(我正在谈论data_vector
),它可以在内存中移动所有以前的数据。但是你为你的线程取一个单元格的(引用)地址,然后再次推回(使之前的引用无效)
这会导致你崩溃。
为了方便修复,请在创建后添加data_vector.reserve(num_threads);
。
修改 - thread_sum_up
void thread_sum_up(const size_t n, size_t& count) {
size_t i;
for (i = 0; i < n; ++i); // see that last ';' there? means this loop is empty. it shouldn't be there
count = i; // You're just setting count to be i. why do that in a loop? Did you mean +=?
}
答案 1 :(得分:1)
崩溃的原因可能是std :: ref(data_vector [i])被data_vector中的下一个push_back无效。由于您知道线程数,因此在开始生成线程之前执行data_vector.reserve(num_threads)以防止引用失效。
答案 2 :(得分:1)
当您通过调用push_back
调整向量大小时,可能必须重新分配存储空间,从而导致对包含值的引用失效。这会导致线程写入未分配的内存,这是未定义的行为。
您的选择是预先分配您需要的尺寸(vector::reserve
是一个选项),或选择其他容器。