You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在有界缓冲区(生产者-消费者)问题实现中遭遇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;
}

关键修改点说明

  1. 线程创建参数修正:把producer()改成producer,consumer()改成consumer,传递函数指针而不是直接调用函数,避免段错误。
  2. 线程ID数组存储:用两个数组分别存储生产者和消费者线程的ID,确保每个线程都能被pthread_join等待,避免程序提前退出。
  3. 调整信号量与互斥锁顺序:先等待信号量(确保有可用资源/产品),再加锁操作缓冲区,操作完成后先解锁再通知信号量,彻底避免死锁问题。

内容的提问来源于stack exchange,提问作者PlanetX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 17:02:42