在有界缓冲区(生产者-消费者)问题实现中遭遇Segmentation fault(core dumped)的原因分析与修复方法咨询
分析与修复:生产者/消费者代码的Segmentation Fault及执行不完整问题
嘿,我来帮你拆解这段代码里的问题,以及给出对应的修复方案~
为什么会出现Segmentation Fault?
核心问题有两个,其中第一个直接触发了段错误:
1. 线程创建时传递了错误的函数参数
看你创建线程的代码:
pthread_create(&T1,NULL,producer(),NULL);
这里你直接调用了producer()函数,而不是传递函数指针。producer()的返回值是void*(实际返回NULL),pthread_create的第三个参数需要的是线程入口函数的指针,你传了NULL进去,线程启动时会尝试调用这个NULL指针,直接触发Segmentation Fault。同理,consumer()的调用也犯了同样的错误。
2. 线程ID管理错误
你只用了一个pthread_t T1变量来存储所有线程的ID,每次创建新线程都会覆盖之前的ID值。最后你只pthread_join了最后一个创建的线程,其他线程还在运行时程序就可能提前退出,导致资源(互斥锁、信号量)没有正确释放,也会引发不可预期的问题。
为什么生产/消费不完整?
除了段错误,还有一个逻辑错误导致死锁或执行异常:
信号量与互斥锁的顺序颠倒
在生产者和消费者函数里,你先加了互斥锁,再等待信号量:
- 生产者先
pthread_mutex_lock,再sem_wait(&empty):如果缓冲区已经满了(empty信号量为0),生产者会一直持有互斥锁等待,消费者根本拿不到锁去消费,导致死锁,生产无法继续。 - 消费者先
pthread_mutex_lock,再sem_wait(&full):如果缓冲区为空(full信号量为0),消费者持有锁等待,生产者拿不到锁生产,同样死锁。
修复后的完整代码
#include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<semaphore.h> // buffer keeps track of the number of items produced and consumed int buffer = 0; pthread_mutex_t lock; // full and empty are used to keep track of the spaces empty and filled by the items sem_t full,empty; void *producer(void *arg) { sem_wait(&empty); // 先等空缓冲区 pthread_mutex_lock(&lock); // 再加锁操作缓冲区 buffer++; printf("Producer produced %d \n",buffer); pthread_mutex_unlock(&lock); // 先解锁 sem_post(&full); // 再通知有新产品 return NULL; } void *consumer(void *arg) { sem_wait(&full); // 先等有产品 pthread_mutex_lock(&lock); // 再加锁操作缓冲区 printf("Consumer consumes %d \n",buffer); buffer--; pthread_mutex_unlock(&lock); // 先解锁 sem_post(&empty); // 再通知有空位 return NULL; } int main() { const int THREAD_COUNT = 10; pthread_t producers[THREAD_COUNT]; pthread_t consumers[THREAD_COUNT]; pthread_mutex_init(&lock,NULL); sem_init(&empty,0,10); sem_init(&full,0,0); // 创建所有生产者线程 for(int i=0;i<THREAD_COUNT;i++) { pthread_create(&producers[i],NULL,producer,NULL); // 传递函数指针,不调用函数 } // 创建所有消费者线程 for(int i=0;i<THREAD_COUNT;i++) { pthread_create(&consumers[i],NULL,consumer,NULL); // 同样传递函数指针 } // 等待所有生产者线程结束 for(int i=0;i<THREAD_COUNT;i++) { pthread_join(producers[i],NULL); } // 等待所有消费者线程结束 for(int i=0;i<THREAD_COUNT;i++) { pthread_join(consumers[i],NULL); } pthread_mutex_destroy(&lock); sem_destroy(&empty); sem_destroy(&full); return 0; }
关键修改点说明
- 线程创建参数修正:把
producer()改成producer,consumer()改成consumer,传递函数指针而不是直接调用函数,避免段错误。 - 线程ID数组存储:用两个数组分别存储生产者和消费者线程的ID,确保每个线程都能被
pthread_join等待,避免程序提前退出。 - 调整信号量与互斥锁顺序:先等待信号量(确保有可用资源/产品),再加锁操作缓冲区,操作完成后先解锁再通知信号量,彻底避免死锁问题。
内容的提问来源于stack exchange,提问作者PlanetX
相关产品推荐
相关产品推荐

