pthread_create 上的分段错误
Posted
技术标签:
【中文标题】pthread_create 上的分段错误【英文标题】:Segmentation Fault on pthread_create 【发布时间】:2018-03-28 01:53:12 【问题描述】:我对以下 C 代码有疑问。代码本身应该创建 5 个线程来模拟餐饮哲学家问题,其中线程正在访问共享数据。代码如下:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
//creation of the mutex lock, condition variables, and state
pthread_mutex_t mutex;
pthread_cond_t cond_var[5];
enumTHINKING, HUNGRY, EATINGstate[5];
//test if possible to get forks
void test(int pNumber)
//start eating if the adjacent philosophers aren't eating
if((state[(pNumber + 1) % 5] != EATING) && (state[(pNumber + 4) % 5] != EATING))
state[pNumber] = EATING;
//signal self if test() called by another thread
pthread_cond_signal(&cond_var[pNumber]);
//used to make the philosopher's forks unavailable
void pickup_forks(int pNumber)
//get lock
pthread_mutex_lock(&mutex);
//set state to hungry
state[pNumber] = HUNGRY;
printf("Philosopher %d is HUNGRY\n", pNumber);
//attempt to begin eating. if unable to, will wait
test(pNumber);
while(state[pNumber] != EATING)
pthread_cond_wait(&cond_var[pNumber], &mutex);
//switched the order of the arguments
//release lock
pthread_mutex_unlock(&mutex);
//allow neighbors to use philosopher's forks
void release_forks(int pNumber)
//get lock
pthread_mutex_lock(&mutex);
//set own state to thinking
state[pNumber] = THINKING;
//tell adjacent philosophers to try to eat
test(((pNumber + 1) % 5));
test(((pNumber + 4) % 5));
//release lock
pthread_mutex_unlock(&mutex);
//used by the thread to run the philosophers
void *runPhilosopher(void *x)
//which philosopher it is
int pNumber = *((int*) x);
//initially thinking
state[pNumber] = THINKING;
printf("Philosopher %d is THINKING\n", pNumber);
//"think" for a random amount of time between 1-3 seconds
int sleepTime = rand() % 3 + 1;
sleep(sleepTime);
//each philosopher eats a total of 5 times
int i = 0;
for(i = 0; i < 5; i++)
//get the forks and begin eating
pickup_forks(pNumber);
//eating time
sleep(2);
//put down forks and resume thinking
release_forks(pNumber);
sleepTime = rand() % 3 + 1;
sleep(sleepTime);
printf("Philosopher %d has finished eating\n", pNumber);
int main(int argc, char *argv[])
pthread_mutex_init(&mutex, NULL);
int i = 0;
for(i = 0; i < 5; i++)
pthread_cond_init(&cond_var[i], NULL);
pthread_t tid[5]; //thread id
pthread_attr_t attr; //set of thread attributes
pthread_create(&tid[0], NULL, runPhilosopher, (void *) 0);
pthread_create(&tid[1], NULL, runPhilosopher, (void *) 1);
pthread_create(&tid[2], NULL, runPhilosopher, (void *) 2);
pthread_create(&tid[3], NULL, runPhilosopher, (void *) 3);
pthread_create(&tid[4], NULL, runPhilosopher, (void *) 4);
//wait for threads to finish
for(i = 0; i < 5; i++)
pthread_join(tid[i], NULL);
return 0;
我在使用 gedit 的 Linux 虚拟机上。该程序编译得很好,但是在尝试运行它时,我得到一个“分段错误”错误,这是来自尝试的线程创建,根据 gdb。我发现这里的相关问题都没有适用于我的程序。
我尝试过的事情:
注释掉绝大多数代码并尝试创建一个简单地运行 runPhilosopher 的线程,该线程已被剥离为仅一个 printf 语句。这导致代码似乎没有创建线程,因为没有输出。 用 &attr 替换线程创建中的 NULL。这将错误更改为已中止,但没有执行任何其他操作。 对所有这些都使用一个线程 ID,就像我在之前的程序中所做的那样。这没什么区别。 其他一些我不记得的零碎事情是否有人看到了我忽略的简单解决方案,或者我的程序中是否存在严重缺陷?我无法理解问题可能是什么,但我完全承认我对 C 语言并不精通。任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:你的问题在这里:
int pNumber = *((int*) x);
在调用pthread_create()
时将整数转换为指针,但随后将其转换为线程函数中的指针并继续取消引用。
相反,试试
int pNumber = (int) x;
请注意,这可能会导致编译器警告sizeof(int) != sizeof(void*)
。您可能想先投射到uintptr_t
。
或者,您可以将int
存储在局部变量中,并将其地址传递给pthread_create
。只需确保在包含函数返回之前所有线程都已停止。
或者,您可以malloc
将此int
作为成员的结构,并将指针传递给它。
【讨论】:
不是唯一的问题,但这个修复让我找到了解决问题的正确方向,谢谢!以上是关于pthread_create 上的分段错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 pthread_create 时出现“分段错误(核心转储)”