Home > OS >  How to fix a Segmentation Fault in pthread_create call
How to fix a Segmentation Fault in pthread_create call

Time:04-13

I am having an issue with my current code. I am working on a project where I am using threads to read a group of files from the terminal and tell how many lines there are in the individual and total grouping of files. My question is that when I run the code I get a core dump and when I run my code through gdb I get a segmentation fault at the pthread_create call. Is it because of my implementation or is it due to something else in my code?

#define NUM_THREADS 12
struct thread_data{
    char *thread_id;
    int count;
};

struct thread_data thread_data_array[NUM_THREADS];

void* filecount(void * thread_arg){
    char thread_id;
    int count;
    struct thread_data *thread;

    thread = (struct thread_data *) thread_arg;
    thread_id = *thread->thread_id;
    count = thread->count;

    FILE *fp = fopen(&thread_id, "r");
    if (fp == NULL) {
        fprintf(stderr, "Cannot open %s\n", thread_id);
        exit(-1);
    }

    for (char c = getc(fp); c != EOF; c = getc(fp))
        if (c == '\n')
            count  ;

    fclose(fp);
    pthread_exit(NULL);
}

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

    if (argc == 1)
        return 0;

    pthread_t threads[argc];
    int t, total_count, count;
    total_count = 0;

    for(t=1; t<argc; t  ){
        thread_data_array[t].thread_id = argv[t];
        thread_data_array[t].count = count;
        printf("Creating thread for file: %s",thread_data_array[t].thread_id);

        ///This is the line in question///
        pthread_create(&threads[t], NULL,filecount,(void *) &thread_data_array[t]);

        printf("File name: %s --- line count: %d", thread_data_array[t].thread_id, total_count);
        total_count  = thread_data_array[t].count;
    }
    printf("Total line count: %d", total_count);
    pthread_exit(NULL);
}

CodePudding user response:

To summarize some of the comments:

This

char thread_id;
thread_id = *thread->thread_id;

will give you the first character of the filename. So while &thread_id is the correct type (char *) for the first argument of fopen, its not a pointer to a null terminating string. This is undefined behaviour.

In

thread_data_array[t].count = count;

count is uninitialized, and its value is indeterminate. This is undefined behaviour.

You need to wait for each thread to finish before you use its result. pthread_join is the function to use here.

getc (fgetc) returns type int, which allows for the check against EOF. Narrowing to char removes the ability to properly test for EOF.

thread_data_array should match the threads array in size.

Here is a refactored program:

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

struct thread_data {
    char *thread_id;
    int count;
};

void *filecount(void *thread_arg){
    struct thread_data *arg = thread_arg;

    FILE *fp = fopen(arg->thread_id, "r");

    if (fp == NULL) {
        fprintf(stderr, "Cannot open %s\n", arg->thread_id);
        pthread_exit(NULL);
    }

    for (int c = getc(fp); c != EOF; c = getc(fp))
        if (c == '\n')
            arg->count  ;

    fclose(fp);

    return NULL;
}

int main(int argc, char *argv[]){
    if (argc == 1)
        return 0;

    argv  ;
    argc--;

    pthread_t threads[argc];
    struct thread_data thread_data_array[argc];
    int total_count = 0;

    for (int i = 0; i < argc; i  ) {
        thread_data_array[i].thread_id = argv[i];
        thread_data_array[i].count = 0;
        pthread_create(&threads[i], NULL, filecount,(void *) &thread_data_array[i]);
    }

    for (int i = 0; i < argc; i  ) {
        pthread_join(threads[i], NULL);
        total_count  = thread_data_array[i].count;
    }

    printf("Total line count: %d\n", total_count);
}
  • Related