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);
}