многопоточная программа для выполнения подсчета частоты - ошибка сегментации - PullRequest
2 голосов
/ 14 марта 2020
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

pthread_mutex_t lock;

//typedef struct for a word
typedef struct {
    char word[101];
    int frequency;
}Word;

//struct for thread
struct ft{
    char* fileName;
    int start;
    int stop;
};

//compare frequency of 2 words 
int compareWords(const void *f1, const void *f2){
    Word *a = (Word *)f1;
    Word *b = (Word *)f2;
    return (b->frequency - a->frequency);
}

//count frequency of a word
void countFrequency(void *arg){

    pthread_mutex_lock(&lock);

    int i, c;
    struct ft* fi = (struct ft*)arg;
    FILE *file = fopen(fi->fileName,"r");
    fseek(file,fi->start,SEEK_SET);
    for(i = 0; i < fi->stop - fi->start; i++){
        c = getc(file);
        //printf("%d\n", c);
        //frequency count
    }

    fclose(file);

    pthread_mutex_unlock(&lock);
}

int main (int argc, char **argv){

    //variabies for <time.h>
    struct timespec startTime;
    struct timespec endTime;
    clock_gettime(CLOCK_REALTIME, &startTime);

    /*------------main------------------*/

    //variables
    int nthreads;   //number of threads
    int chunkSize;  //each threas processing size

    //if user input is not correct, inform
    if(argc < 3){ 
       printf("./a.out text_file #ofthreads \n");
       exit(-1);
    }


    nthreads = atoi(argv[2]);
    chunkSize = sizeof(argv[1])/nthreads;

    //declare threads and default attributes
    pthread_t threads[nthreads];
    pthread_attr_t attr;
    pthread_attr_init(&attr);

    //run threads in parallel
    int i; 
    for (i = 0; i < nthreads; i++){
       struct ft data[nthreads];
       data[i].start = i*chunkSize;
       data[i].stop = data[i].start+chunkSize;
       data[i].fileName = argv[1];


       // Create a new thread for every segment, and count word  frequency for each
       pthread_create(&threads[i], &attr, (void*) countFrequency, (void*) &data[i]);

    }

    //wait for results (all threads)
    for (i = 0; i < nthreads; i++){
       pthread_join(threads[i], NULL);
    } 

       //func of <time.h>
       clock_gettime(CLOCK_REALTIME, &endTime);
       time_t sec = endTime.tv_sec - startTime.tv_sec;
       long n_sec = endTime.tv_nsec - startTime.tv_nsec;
       if (endTime.tv_nsec < startTime.tv_nsec)
        {
        --sec;
        n_sec = n_sec + 1000000000L;
        }
       printf("Total Time was %ld.%09ld seconds\n", sec, n_sec);
}

Я работаю над этой программой, чтобы использовать несколько потоков для чтения и обработки большого текстового файла и выполнения частоты подсчета слов из 10 самых распространенных слов в тексте, длина которых превышает 6 символов. Но я продолжаю получать ошибку ошибки сегментации, я не уверен почему, у кого-нибудь есть какие-либо идеи.?

1 Ответ

0 голосов
/ 15 марта 2020

Этот код:

   for (i = 0; i < nthreads; i++){
       struct ft data[nthreads];

объявляет data, который является действующим (разрешенным к использованию) в течение этого времени для l oop. Этот код:

      pthread_create(&threads[i], &attr, (void*) countFrequency, (void*) &data[i]);
   }

передает адрес data в потоки и затем выходит из l oop. Как только l oop завершено, data больше не является активным, и любой доступ к нему ведет к неопределенному поведению.

Компилятор может свободно записывать что-либо еще в память, где data используется для be.

Непосредственная причина cra sh заключается в том, что если один из потоков не выполнит fopen до того, как data будет перезаписан, то fopen может завершиться ошибкой и вы не проверяете ошибку в fopen.

PS

Как отметил Эраклон, этот код: chunkSize = sizeof(argv[1])/nthreads; будет делить sizeof(char*) (4 или 8 в зависимости от будь то сборка для 32-битной или для 64-битной) по количеству потоков. Это вряд ли то, что вы хотите, и даст chinkSize==0 для nthreads > 4 на 32-битных и nthreads > 8 на 64-битных машинах.

PPS

В вашей программе также есть ошибка параллелизма: поскольку каждый из вызовов countFrequency блокирует одни и те же lock на все время , они все будут работать в последовательности (один за другим), а не параллельно. Таким образом, ваша программа будет работать медленнее, чем если бы вы просто выполняли всю работу в основном потоке.

...