2015-08-15 2 views
-1

Я уже несколько месяцев ломаю голову над этой программой. Это было задание класса, которое я взял в прошлом семестре, и пока я проходил, я никогда не смог бы правильно выполнить это одно задание (Seg Fault). Я приветствую любую помощь или советы, но я очень благодарен за объяснения ответов на вопросы.C проблема с сегментацией сегментации многопоточной рассылки

Эта программа должна получить имя файла, которое содержит список имен файлов (240 для моего примера). Эти файлы находятся в папке в том же каталоге, что и список и программа. Предполагается, что эта программа возьмет этот список и проанализирует его для 4 потоков, равномерно разбивая имена файлов для каждого потока (60 на поток для моего примера). Каждый поток затем принимает этот список из 60 имен файлов и каждый раз открывает каждый файл, выполняя функцию WordCount для каждого файла. После того как потоки выполняют свои задачи, они должны печатать результаты для каждого файла, чтобы каждый поток в своем собственном блоке (то есть результаты Thread1, результаты Thread2, результаты 3-го и т. Д.).

Я отлаживал совсем немного и знаю, что вплоть до создания нитей все работает так, как предполагается. Моя проблема, кажется, во время запуска/выполнения потока. Я попытался добавить мьютекс в микс, но, к сожалению, это не помогло. Мне кажется, что что-то не хватает или что-то думает, потому что некоторые из моих товарищей по классу показали мне гораздо более компактный код. Пожалуйста помогите. Благодаря!

Вот Main:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#define MaxLine 200 
#define NUMTHREADS 4 

char Line[MaxLine]; 
pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER; 

typedef struct thread { 
    int id; 
    char file; 
}ThreadData; 

/* ThreadFunction will give each thread its processes to execute */ 
void *threadFunc (void *td) { 
    ThreadData *data = (ThreadData*)td; 
    int thread_num=data->id; 
    char filename=data->file; 
    printf("thread debug tid: %d and file: %c",thread_num, filename); 
    pthread_mutex_trylock(&Lock); 
    FILE *fn = fopen(filename, "r"); 
    if (fn == NULL) { 
     error("ERROR: Opening file"); 
     return 1; 
    } 
    while (fgets(Line, sizeof(Line), fn) != NULL) { 
     CountWord(thread_num, Line); 
    } 
    fclose(fn); 
    free(data); 
    pthread_mutex_unlock(&Lock); 
    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]){ 
    char buf[20]; 
    int c, i, t, tnum, QUEUETOTAL; 
    pthread_t thread[NUMTHREADS]; 
    ThreadData td[NUMTHREADS]; 

    if (argc != 2){ 
     fprintf(stderr,"ERROR: Usage must be Countfile filename\n", argv[0]); 
     exit(0); 
    } 
    char const* const filename = argv[1]; 
    FILE* file = fopen(filename, "r"); 
    if (file == 0){ 
     printf("Could not open file!\n"); 
     exit(0); 
    } 

    /* Count iterations of while loop to divide files among threads. */ 
    while (fgets(Line, sizeof(Line), file)){ 
     QUEUETOTAL++; 
    } 

    /* Divide work for threads. */ 
    int thread2taskstart=(QUEUETOTAL/NUMTHREADS); //60 
    int thread3taskstart=(QUEUETOTAL/NUMTHREADS)*2; //120 
    int thread4taskstart=(QUEUETOTAL/NUMTHREADS)*3; //180 
    // QUEUETOTAL = 240 

    rewind(file); 
    FILE *tempfile1 = fopen("temp1.txt","w"); 
    for (i=0; i<thread2taskstart; i++) { 
     // populate tempfile1 with entries 1-60 
     if(fgets(Line,sizeof(Line),file)!=NULL) { 
      fputs(Line,tempfile1); 
      //printf("Debug temp1: %s",Line); 
     } 
    } 
    fclose(tempfile1); 
    FILE *tempfile2 = fopen("temp2.txt","w"); 
    for (i=thread2taskstart; i<thread3taskstart; i++) { 
     // populate tempfile2 with entries 60-120 
     if(fgets(Line,sizeof(Line),file)!=NULL) { 
      fputs(Line,tempfile2); 
      //printf("Debug temp2: %s",Line); 
     } 
    } 
    fclose(tempfile2); 
    FILE *tempfile3 = fopen("temp3.txt","w"); 
    for (i=thread3taskstart; i<thread4taskstart; i++) { 
     // populate tempfile3 with entries 120-180 
     if(fgets(Line,sizeof(Line),file)!=NULL) { 
      fputs(Line,tempfile3); 
      //printf("Debug temp3: %s",Line); 
     } 
    } 
    fclose(tempfile3); 
    FILE *tempfile4 = fopen("temp4.txt","w"); 
    for (i=thread4taskstart; i<=QUEUETOTAL; i++) { 
     // populate tempfile3 with entries 180-240 
     if(fgets(Line,sizeof(Line),file)!=NULL) { 
      fputs(Line,tempfile4); 
      //printf("Debug temp4: %s",Line); 
     } 
    } 
    fclose(tempfile4); 
    fclose(file); 

    /* Prepare parameters & launch (4) threads. Wait for threads 
    to finish & print out results as specified in assignment. */ 
    printf("Counting files …\n"); 

    for(t=0;t<NUMTHREADS;t++){ 
     tnum=t+1; 
     snprintf(buf, "temp%d.txt", tnum); 
     printf("debug tnum and array: %d and %s\n",tnum, buf); 
     td[t].id = tnum; 
     td[t].file = buf; 
     // Creates a new thread for each temp file. 
     pthread_create(&thread[t], NULL, threadFunc, td); 
    } 
    // Joins threads. 
    printf("debug: printing threads \n"); 
    for(t=0;t<NUMTHREADS;t++){ 
    pthread_join(thread[t], NULL); 
    printf("------------------------- Processes finished for Thread %d ----------------------- \n",t+1); 
    } 
    return 0; 
} 

Вот граф Функция:

#include <stdio.h> 

int CountWord(int tinfo, char cfile){ 
    int i; 
    int ccount = 0; 
    int wcount = 0; 
    int lcount = 0; 
    FILE *fname; 
    char fn[strlen(cfile) + 18]; 
    sprintf(fn, "./CountingFolder/%s", cfile); 
    printf("Debug: %s\n", fn); 
    fname = fopen(fn, "r"); 
    if (fname == NULL) { 
     error("ERROR: Opening file"); 
    } 
    while ((i = fgetc(fname)) != EOF){ 
     if (i == '\n') { 
      lcount++; 
     } 
     if (i == '\t' || i == ' '){ 
      wcount++; 
     } 
     ccount++; 
    } 
    printf("Threadid %d processes %s which has %d characters, %d words and %d lines\n", tinfo, cfile, ccount, wcount, lcount); 
    fclose(fname); 
    return 0; 
} 
+0

Вы используете 'pthread_mutex_trylock', не проверяя результат.Что происходит, когда не удалось получить блокировку? – Kninnug

+0

в функции: CountWord(): когда файл не открывается, НЕ пытайтесь прочитать из файла – user3629249

+0

в функции: CountWord(): в цикле «while»: рассмотрите условие, в котором строка во входном файле содержит некоторые комбинация вкладок и пробелов без других символов, включая/особенно в начале строки. И правильный текст имеет 2 пробела после окончания каждого предложения. Предложите: 1) искать stackoverflow для примеров (возможно, без нескольких потоков) извлечения слов из файла. Хорошие примеры будут иметь две государственные машины, реализованные в словах и не в словах. начать в состоянии не в словах. – user3629249

ответ

3

1) Вероятно, опечатка. Но

int CountWord(int tinfo, char cfile){ .. }

должно быть

int CountWord(int tinfo, char *cfile){ .. } 

2) Вы передаете то же buf все потоки из main(). Гонка данных и неопределенное поведение.

3) Ни один из вызовов snprintf() не принимает аргумент size. Неопределенное поведение.

4) Поскольку все потоки работают с разными данными, вам вообще не нужна блокировка.

5) Вы не выделили массив td. Поэтому вы не можете вызвать free(data); в функции потока. Неопределенное поведение.

Может быть больше проблем с кодом, но segfault, скорее всего, из-за (3) или (5).

+0

(4) В потоках используется глобальная переменная 'Line', хотя ... – Kninnug

+0

Право. нет необходимости использовать блокировку, потому что переменная, которая читает строки, является глобальной. Но она должна быть локальной переменной. –

+0

@BlueMoon: глобальные блоки не нуждаются в блокировке? Почему это так? –

0

В коде здесь

snprintf(buf, "temp%d.txt", tnum); 
printf("debug tnum and array: %d and %s\n",tnum, buf); 
td[t].id = tnum; 
td[t].file = buf; 

последняя строка присваивает указатель в file поле этой структуры

typedef struct thread { 
    int id; 
    char file; 
}ThreadData; 

Не должна ли она быть char *file;? У меня нет thread.h в MSVC, поэтому я не могу его скомпилировать. Наверняка у вас есть все предупреждения?

+0

Он не должен компилироваться, если это так. Определенно, что-то странное происходит здесь (возможно, отсутствие глубокой копии), но это также может быть проблемой с вопросом. –

Смежные вопросы