2

プログラムは、渡された引数に基づいてx個のスレッドを作成することになっています。argv [1]はメインがスリープすることになっている量、argv [2]はプロポージャースレッドの数、argv[3]はコンシューマースレッドの数です。プログラムは正常にコンパイルされ、実行に使用しているコマンドは次のとおりです。program 1011

私はしばらくの間このコードを見つめていましたが、セグメンテーション違反の原因を見つけることができないようです。たぶん、2番目の目ですぐにそれを選ぶことができるでしょう。

#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.outb main starts

誰かが既に述べたように、プロデューサー関数には初期化されていないポインターがありますunsigned int *seed;

また、このプログラムは、通常のロック解除の問題とともに、それに関連するウェイクアップの問題を失いましplaced++た (関数の挿入項目のように、実行する前に insert_item スレッドのコンテキストが切り替えられた場合はどうなりますか? )

于 2012-05-08T22:33:10.983 に答える