2

我正在对 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)

有人知道这里发生了什么吗?

先感谢您!

4

3 回答 3

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 +=?
}
于 2013-11-01T17:33:33.300 回答
1

崩溃的原因可能是 std::ref(data_vector[i]) 被 data_vector 中的下一个 push_back 无效。由于您知道线程数,因此请在开始生成线程之前执行 data_vector.reserve(num_threads) 以防止引用无效。

于 2013-11-01T17:30:31.237 回答
1

当您通过调用来调整向量的大小时push_back,可能必须重新分配存储空间,从而导致对所包含值的引用无效。这会导致线程写入未分配的内存,这是未定义的行为。

您的选择是预先分配您需要的大小(vector::reserve是一个选项),或者选择不同的容器。

于 2013-11-01T17:31:32.863 回答