简体   繁体   English

将std :: thread分配给向量时出现segfault <std::thread>

[英]segfault when assigning an std::thread to a vector<std::thread>

This segfaults: 此段错误:

std::vector<std::thread>    _pool;
State &                     _state;

...

for(uint32_t n = 0; n < nThreads; ++n)
    _pool[n]  = std::thread(_thFunction, std::ref(_state));

This does not: 这不是:

std::vector<std::thread>    _pool;
State &                     _state;

...

for(uint32_t n = 0; n < nThreads; ++n)
    _pool.push_back( std::thread(_thFunction, std::ref(_state)) );

The difference in the use of push_back to the vector instead of using assignment to a specific entry in the vector. 向向量使用push_back而不是对向量中的特定条目使用分配的区别。

_thFunction is an std::function. _thFunction是std :: function。

When I apply a pool.reserve(10) to the first block of code, I still get a segfault on the first assignment. 当我将pool.reserve(10)应用于第一个代码块时,我仍然在第一个分配上遇到段错误。

I suspect that this is related to move semantics, but I'm not sure. 我怀疑这与移动语义有关,但我不确定。 What's going on here? 这里发生了什么?

A stacktrace from gdb seems to indicate a null this pointer: 来自gdb的stacktrace似乎指示此指针为null:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004092e5 in std::thread::joinable (this=0x0) at /usr/include/c++/4.8.3/thread:162
162     { return !(_M_id == id()); }
(gdb) backtrace
#0  0x00000000004092e5 in std::thread::joinable (this=0x0) at /usr/include/c++/4.8.3/thread:162
#1  0x000000000040927a in std::thread::operator=(std::thread&&) (this=0x0, 
    __t=<unknown type in /home/stackuser/src/dsl/build/debug/server/dsl, CU 0x0, DIE 0x37b88>)
    at /usr/include/c++/4.8.3/thread:150
#2  0x000000000041350d in ThreadPool<std::function<void (State&)> >::ThreadPool(State&, unsigned int, std::function<void (State&)>) (this=0x69aed0, state=..., nThreads=2, thFunction=...)
    at src/server/ThreadPool.h:38
#3  0x0000000000408405 in Application::Application (this=0x6946e0) at src/server/Application.cpp:69
#4  0x0000000000455594 in Singleton<Application>::CreateInstance () at src/server/Singleton.h:12
#5  0x0000000000454997 in main (argc=1, argv=0x7fffffffdc98) at src/server/main.cpp:85

Read reference documentation of the operator[] that you're using. 阅读您正在使用的operator[]参考文档

Returns a reference to the element at specified location pos. 返回对在指定位置pos的元素的引用。 No bounds checking is performed. 不执行边界检查。

So, when you call _pool[n] on an empty vector, you get a reference to a non-existing object and undefined behaviour ensues. 因此,当您在空向量上调用_pool[n]时,将获得对不存在对象的引用,从而导致未定义的行为。 Assigning a value to this reference does not grow the vector. 给该参考分配一个值不会使向量增长。

reserve does not add any elements to the vector either. reserve也不向向量添加任何元素。 It simply increases the capacity of the vector which means that inserting elements to the end won't invalidate iterators / references / pointers to elements until that capacity is reached. 它只是增加了向量的容量 ,这意味着将元素插入到末端将不会使迭代器/引用/元素的指针无效,直到达到该容量为止。

resize(n) would create n objects in the vector which I suspect you are expecting reserve to do and it's excellent way to initialize the vector with identical objects when you don't know the count and the value at the time the vector is constructed. resize(n)会在向量中创建n对象,我怀疑您希望reserve该对象,这是在不知道构造向量时的计数和值的情况下用相同对象初始化向量的好方法。 But if you were to overwrite the objects anyway, push_back with reserve would waste less resources. 但是,如果仍然要覆盖对象,则使用reserve push_back会浪费更少的资源。 Or, if you know the values that you want in the vector, you could simply fill the vector using the constructor. 或者,如果您知道向量中想要的值,则可以使用构造函数简单地填充向量。

It has nothing to do with move semantics, you're simply trying to assign to elements of a vector that don't exist. 它与移动语义无关,您只是试图将其分配给不存在的向量元素。

_pool.push_back() creates a new element, but _pool[n] does not. _pool.push_back()创建一个新元素,但_pool[n]没有。

reserve() does not create elements either, it just allocates memory for them (but does not construct them) reserve()也不创建元素,它只是为它们分配内存(但不构造它们)

Either resize the vector so the elements exist before you assign to them, or use push_back resize向量的resize以使元素存在,然后再分配给它们,或者使用push_back

std::vector::reserve will only "prepare" the vector to grow, but the logical size of the vector is still 0. So _pool[n] = ... is still invalid. std::vector::reserve只会“准备”向量增长,但是向量的逻辑大小仍然为0。 So _pool[n] = ...仍然无效。 You should use std::vector:resize instead. 您应该改用std::vector:resize

Using reserve() does not create any elements - it only makes sure that when you do create them, no allocation will be performed. 使用reserve()不会创建任何元素-仅确保在创建它们时不会执行任何分配。 Create the vector with 10 empty elements like that: 创建具有10个空元素的向量,如下所示:

std::vector<std::thread>    _pool(10);

and your first example will work 你的第一个例子将工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM