2016-12-05 117 views
0

我有一個程序應該將文件的內容完全複製到使用多個線程的另一個文件中。閱讀器線程從文件中讀取一行並將其存儲在循環緩衝區中。寫入器線程然後從緩衝區讀取並寫入文件。但是,我收到了分段錯誤,並且沒有寫入文件。任何想法爲什麼我得到一個分段錯誤,或者有什麼辦法,我可以找出是什麼導致了錯誤?運行程序時出現分段錯誤並改變輸出

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <pthread.h> 
#include <semaphore.h> 

FILE *inputFile; 
FILE *outputFile; 

pthread_mutex_t mutex; 

int endOfFile = 0; 

typedef struct bufferStruct{ 
    int capacity; 
    int size; 
    int head; 
    int tail; 
    char **data; 
}buffer; 

buffer * bufferInit(int maxElements){ 
    buffer *buf; 
    buf = (buffer *)malloc(sizeof(buffer)); 

    buf->data = (char**)malloc(sizeof(char*)*maxElements); 
    buf->size = 0; 
    buf->capacity = maxElements; 
    buf->head = 0; 
    buf->tail = -1; 

    return buf; 
} 

void popFront(buffer *buf){ 
    if(buf->size != 0){ 
     free(buf->data); 
     buf->size--; 
     buf->head++; 
     if(buf->head == buf->capacity){ 
      buf->head = 0; 
     } 
    } 
    return; 
} 

char* front(buffer *buf){ 
    if(buf->size != 0){ 
     return buf->data[buf->head]; 
    } 

    return NULL; 
} 

void pushBack(buffer *buf, char *data){ 
    if(buf->size == buf->capacity){ 
     printf("Queue is Full\n"); 
    } 

    else{ 
     buf->size++; 
     buf->tail = buf->tail + 1; 

     if(buf->tail == buf->capacity){ 
      buf->tail = 0; 
     } 

     buf->data[buf->tail] = (char *) malloc((sizeof data + 1)* sizeof(char)); 

     strcpy(buf->data[buf->tail], data); 
    } 
    return; 
} 

buffer *buf; 

void* reader(void* arg){ 
    char line[1024]; 
    while(endOfFile != 1){ 
     fgets(line, sizeof(line), inputFile); 
     printf("Line read: %s", line); 

     pushBack(buf, line); 

     if(feof(inputFile)){ 
      endOfFile = 1; 
     } 
    } 
    pthread_exit(0); 
} 

void* writer(void* arg){ 
    char *line; 
    while(endOfFile != 1){ 
     pthread_mutex_lock(&mutex); 
     line = front(buf); 
     fputs(line, outputFile); 
     popFront(buf); 
     pthread_mutex_unlock(&mutex); 
    } 
    pthread_exit(0); 
} 

int main(int argc, char **argv){ 
    if (argc < 4) { 
     printf("Usage: %s <input file> <output file> <number>\n", argv[0]); 
     exit(-1); 
    } 

    inputFile = fopen(argv[1], "r"); 
    outputFile = fopen(argv[2], "w"); 
    int numOfThreads = atoi(argv[3]); 

    buf = bufferInit(16); 

    pthread_t readerTids[numOfThreads]; 
    pthread_t writerTids[numOfThreads]; 

    pthread_mutex_init(&mutex, NULL); 

    for(int i = 0; i < numOfThreads; i++){ 
     if(endOfFile != 1){ 
      pthread_attr_t attr; 
      pthread_attr_init(&attr); 
      pthread_create(&readerTids[i], &attr, reader, NULL); 
      pthread_create(&writerTids[i], &attr, writer, NULL); 

      printf("Thread %d created\n", i); 
     } 
    } 

    for (int i = 0; i < numOfThreads; i++) { 
     pthread_join(readerTids[i], NULL); 
     pthread_join(writerTids[i], NULL); 
    } 

    fclose(inputFile); 
    fclose(outputFile); 
} 
+0

閱讀[未定義的行爲](https://en.wikipedia.org/wiki/Undefined_behavior)。躲開它。詳細瞭解[pthreads](https://computing.llnl.gov/tutorials/pthreads/)。編譯所有警告和調試信息('gcc -Wall -Wextra -g')。使用調試器('gdb')來了解更多關於分段錯誤的信息。也可以使用[valgrind](http://valgrind.org/)。你的* fix-my-code *問題是無關緊要的。它看起來像你的線程不夠同步(你可能需要一個互斥體)。 –

+2

您的讀者線程永遠不會鎖定互斥鎖,這意味着您的讀者線程可以隨時修改(buf),即使寫入者線程鎖定了互斥鎖。因此你的程序有一個*競爭條件*並且遇到未定義的行爲。 (另外,你的兩個線程都會在沒有任何同步的情況下訪問全局變量'endOfFile',這也會導致未定義的行爲) –

+0

@JeremyFriesner給了你答案,順便說一句,你可以使用Semaphore來「簡化」syncronization而不是互斥 – Raskayu

回答

0

考慮到讀者線程比寫入者線程慢的可能性。作家線程獨自擁有鎖定,鎖定和解鎖,而不是困擾讀者。當閱讀器尚未更新緩衝區時,如果作者試圖使用緩衝區,該怎麼辦?使用線程同步,例如信號量,它沒有任何所有權問題。

void* reader(void* arg){ 
    char line[1024]; 
    while(endOfFile != 1){ 
     fgets(line, sizeof(line), inputFile); 
     printf("Line read: %s", line); 

     pushBack(buf, line); 

--- Lock semaphore here--- 

     if(feof(inputFile)){ 
      endOfFile = 1; 
     } 
    } 
    pthread_exit(0); 
} 


void* writer(void* arg){ 
    char *line; 
    while(endOfFile != 1){ 

-- Unlock semaphore here--- 

     line = front(buf); 
     fputs(line, outputFile); 
     popFront(buf); 
    } 
    pthread_exit(0); 
} 

與互斥鎖不同,兩個線程之間可以使用相同的信號量。這可以幫助你同步兩個線程。