2

该程序应该根据传递给它的参数创建 x 数量的线程。argv[1] 是 main 应该休眠的数量,argv[2] 是 proprocer 线程的数量,而 argv[3] 是消费者线程的数量。该程序编译良好,我用来运行它的命令是:program 10 1 1

我已经盯着这段代码一段时间了,我似乎无法找到导致分段错误的原因。说不定第二双眼睛就能很快的把它挑出来。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include "buffer.h"

void *producer(void *);
void *consumer(void *);

// Semaphores
sem_t empty;
sem_t full;
pthread_mutex_t mutex;

// Buffer
int placed = 0;
buffer_item buffer[BUFFER_SIZE];
int insert_item(buffer_item item){
    /* INSERT ITEM INTO BUFFER */
    int z;
    sem_wait(&empty);

    //mutex lock
    z = pthread_mutex_lock(&mutex);
    if (z != 0){
        return -1;
    }
    buffer[placed] = item;

    //mutex unlock
    z = pthread_mutex_unlock(&mutex);
    if (z != 0){
        return -1;
    }

       sem_post(&full);
    placed++;
    printf("producer produced %d\n", item);
}

int remove_item(buffer_item *item){
    /* REMOVE ITEM FROM BUFFER */
    int m;
    placed--;
    sem_wait(&full);

    //mutex lock
    m = pthread_mutex_lock(&mutex);
    if (m != 0){
        return -1;
    }
       buffer[placed] = -1;

    //mutex unlock
    m = pthread_mutex_unlock(&mutex);
    if (m != 0){
        return -1;
    }

       sem_post(&empty);
    printf("consumer consumed %d\n", rand);
    return 0;
}

// Main

int main(int argc, char *argv[]){
    int sleepNum, pThreadNum, cThreadNum, p;
    sleepNum = atoi(argv[1]);
    pThreadNum = atoi(argv[2]);
    cThreadNum = atoi(argv[3]);


    // Initialize Semaphores & mutex
    sem_init(&empty, 0, BUFFER_SIZE);
    sem_init(&full, 0, 0);
    pthread_mutex_init(&mutex, NULL);

    // Create producer thread
    pthread_t tid[pThreadNum];

    int g=pThreadNum-1;
    while(g >= 0){
        p = pthread_create(&tid[g], NULL, producer, NULL);
        g--;
    }
    printf("created prod thread");
    // Create consumer thread
    pthread_t kid[cThreadNum];
    g = cThreadNum-1;
    while(g >= 0){
        p = pthread_create(&kid[g], NULL, consumer, NULL);
        g--;
    }

    // Sleep for argv[0]
    sleep(sleepNum);

    // Destroy mutex & semaphores
        sem_destroy(&empty);
        sem_destroy(&full);
        p = pthread_mutex_destroy(&mutex);

    // Exit
    exit(0);
}


// Producer
void *producer(void *param){
    buffer_item rand;
    unsigned int *seed;
    int b;
    while(1){
        sleep(2);
        rand = rand_r(seed);
        b = insert_item(rand);
        if (b < 0){
            printf("Error producing item.");
        }
    }
}

// Consumer
void *consumer(void *param){
    buffer_item rand;
    int d;
    while(1){
        sleep(2);
        d = remove_item(&rand);
        if (d < 0){
            printf("Error removing item");
        }
    }
}

提前致谢!

4

4 回答 4

2

在 Unix 上,您可以通过转储核心并检查 gdb 中的核心文件来从分段错误中获取回溯。

$ ulimit -c <max core file size in 1k blocks>
$ gdb program core
gdb> bt

应该转储回溯,您可以准确地看到哪一行出现了段错误。

于 2012-05-08T21:58:27.223 回答
1

在生产者中,您使用的是未初始化的指针。尝试使用 malloc 为其分配一些内存。我没有确切解释它是什么,因为您将其标记为作业。

也不要依赖 printf 语句的输出来告诉你程序在使用线程时到达了哪里。如果您在每个 printf 之后显式刷新输出流,这会有所帮助,那么您几乎会了解正确的事件序列。

于 2012-05-08T22:09:31.043 回答
0

用-g编译你的程序,gcc -g program.c -lpthread 然后 gdb a.out 设置断点为 b main start ,然后s用于逐步执行,看看它在哪里下降。

正如有人已经提到您的生产者函数具有未初始化的指针unsigned int *seed;

这个程序也失去了与之相关的唤醒问题,以及正常的解锁问题(如函数插入项,如果在执行之前插入项线程上下文切换怎么办placed++。)

于 2012-05-08T22:33:10.983 回答
0

这是一篇很棒的文章,用于查找段错误的原因。

关联

链接镜像在这里,以防万一它发生故障......你永远不知道。

于 2013-06-19T19:55:08.270 回答