以下代码可靠地产生段错误。
#include <vector>
#include <thread>
class Class {
public:
Class(const int integer)
: cinteger(integer), carray(std::array<int, 1>{0})
{}
const int operator()()
{
carray[cinteger] = 0;
return cinteger;
}
private:
int cinteger;
std::array<int, 1> carray;
};
class Worker{
public:
Worker( Class iClass):
wClass(iClass),
thread(&Worker::thread_main, this)
{}
void join(){thread.join();}
private:
Class wClass;
std::thread thread;
void thread_main(){
for(int i = 0; i < 50000; i++)
wClass();
}
};
int main()
{
std::vector<Worker> Workers;
for(int i = 0; i < 4; i++)
Workers.emplace_back(Class(0));
for(int i = 0; i < 4; i++)
Workers[i].join();
return 0;
}
出于某种原因,我不明白,Class 的
cinteger
变量似乎被意外更改了。每次运行代码都会出现这个问题。如果我只生成 3 个工人,它就不会出现。此外,在 Worker 类中进行 1000 次迭代时,问题不会出现。
TBH 我有点不知道这个问题可能来自哪里。
这真的很简单。在您引用
this
的线程中,但是当您在向量中执行emplace_back
时,它最终会导致调整向量的大小并将对象移动到内存中的不同位置。使以前的实例无效。这导致this
在thread_main()
成员函数内部无效和损坏。
除了其他答案提供的原因外,解决此问题的一种简单方法是简单地动态分配
Worker
类。将 vector<Worker>
替换为 std::vector<std::unique_ptr<Worker>>
,并相应地修复插入内容。
这将使您的工作人员对
vector
调整大小引起的重新分配不敏感,这比调用 .reserve
更稳健,因为您不需要提前知道工作人员的数量。Worker
将停留在它所在的位置,它将被动态分配并且不存在于向量中。
如果您 do 知道,那么您可以使用
.reserve
解决方案。