pthread_create在构造函数段错误中
pthread_create in constructor segfault
我发现,在下面的这个小例子中,如果我在结构的构造函数中调用pthread_create,我在调用 pthread_mutex_lock(( 时会随机得到一个段错误。
有时,对于第一位哲学家来说,名字字段是空的。
如果我pthread_create构造函数之后移动到 run(( 函数,则没有段错误。
似乎对所有成员初始化之前都会调用pthread_create。 类的成员初始化列表不应该在调用构造函数体之前完成吗?
感谢您的任何提示!
CLANG 版本 9.0.0 (标签/RELEASE_900/最终版( 目标:x86_64-苹果-达尔文17.7.0
真诚的,乔治
#include <array>
#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>
using namespace std;
struct chopstick
{
pthread_mutex_t mutex;
chopstick()
{
pthread_mutex_init(&mutex,nullptr);
}
~chopstick()
{
pthread_mutex_destroy(&mutex);
}
};
void* feed(void* data);
struct philosopher
{
pthread_t thread;
string name;
unsigned mouthfuls;
chrono::seconds sec;
chopstick &left, &right;
pthread_t& get_thread() { return thread; }
philosopher(const string &s, chopstick &l, chopstick &r): name(move(s)), left(l), right(r), mouthfuls(0)
/*
enable below to avoid segfault
{}
void run()
*/
{
pthread_create(&thread, nullptr, feed, this);
};
};
void* feed(void* data)
{
philosopher & a = *static_cast<philosopher*>(data);
while (a.mouthfuls < 20)
{
pthread_mutex_lock(&a.left.mutex);
pthread_mutex_lock(&a.right.mutex);
cout << "Apostle " << a.name << " thread id " << pthread_self()
<< " acquired a chopstick at count: " << a.mouthfuls << endl;
++a.mouthfuls;
pthread_mutex_unlock(&a.right.mutex);
pthread_mutex_unlock(&a.left.mutex);
}
return nullptr;
}
int main (int argc, char const * argv[])
{
array<string, 12> names {"John", "Thaddeus", "Simon Peter", "James", "Judhas", "Bartholomew", "Matthew", "Philip", "Simon Zealot", "Thomas", "Andrew", "James the Lesser" };
array<chopstick,names.size()> sticks;
vector<philosopher> philosophers;
for (int i=0; i+1<names.size(); ++i)
philosophers.emplace_back( names[i],sticks[i],sticks[i+1] );
philosophers.emplace_back(names[names.size()-1], sticks[0],sticks[names.size()-1]);
//for (philosopher& a: philosophers) a.run(); //<-- enable to avoid segfault
for (philosopher& a: philosophers) pthread_join(a.get_thread(), nullptr);
return 0;
}
std::vector
在代码philosophers.emplace_back()
时调整大小,这可以移动内存中的元素,以便它们以前的地址变得无效,并且feed()
函数最终使用其旧的无效地址访问对象。
解决方法是使philosopher
类不可复制和不可移动,然后使用std::list<philosopher>
或std::forward_list<philosopher>
而不是std::vector<philosopher>
。std::list
和std::forward_list
不会移动内存中的元素,因此能够存储不可复制和不可移动的对象。
您可能还想使用std::thread
而不是pthread_t
,std::mutex
而不是pthread_mutex_t
。std
类是不可复制/可移动的,这将防止您在编译时犯此错误。此外,代码不会检查 pthread 函数的返回值是否存在错误,而std::thread
和std::mutex
会为您执行此操作。
相关文章:
- 为什么PyImport_ImportModule python 3.7.2 中出现段错误?
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- 全局向量导致 C++ 程序结束时出现段错误
- 为什么重载运算符<<打印特征类成员会导致段错误?
- 更改条件段错误
- 使用 TTF_RenderText() 加载字体时获取段错误 TTF_OpenFontRW()
- 注册对对象工厂的调用会导致段错误
- pthread_create在构造函数段错误中
- Nanoflann发现邻居提出段错误
- C++ 中的构造函数、继承、堆栈、堆、this-pointer 和段错误
- 具有unique_ptr的 CRTP 会导致段错误
- 增强纤维work_stealing屏障会导致段错误
- 当我返回指向结构的指针向量时出现段错误
- C++为什么我的代码没有爆炸/段错误?
- Pthread段错误,使用指向main中变量的指针
- C++ 模板中的段错误
- 相当于Windows/MSVC上的段错误?
- 为什么我的 LLVM JIT 实现出现段错误?
- 为什么访问我的引用捕获变量会导致我的 lambda 函数出现段错误?
- 为什么自删除的全局 Vulkan 实例仅在添加层时才导致段错误?