I have problems with my code. It's a multithreading program that executes the following Linux command "# cat | sort | uniq -c | sort -nr". When I try to run the program in a virtual machine, I get a segmentation error, no core dumped. I have tried everything to fix this, but I still get the error. I see that the problem is in the main function and I don't know what it is. Could be either in pthread_join or maybe could be the max number of threads, declared globally. Can someone help me out? This is my code.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_THREADS 0x40
#define MAX_STRING 124ULL
struct string_count_entry {
char* string;
int count;
};
struct string_count {
int nb_string;
struct string_count_entry* entries;
};
struct string_count* string_count_init() {
struct string_count* sc;
sc = malloc(sizeof(sc));
sc->entries = NULL;
sc->nb_string = 0;
return sc;
}
int addstring(struct string_count* pt, char* s) {
int i;
for (i = 0; i < pt->nb_string; i ) {
if (strcmp(pt->entries[i].string, s))
break;
}
if (i == pt->nb_string) {
pt->entries = realloc(pt->entries,
pt->nb_string 1 * sizeof(pt->entries[0]));
if (pt->entries == NULL)
return -1;
pt->nb_string ;
pt->entries[i].string = s;
}
pt->entries[i].count ;
return 0;
}
static inline int Compare(const void* pt1, const void* pt2) {
struct string_count_entry* a = malloc(sizeof(pt2));
struct string_count_entry* b = malloc(sizeof(pt1));
if (a->count == b->count)
return strcmp(a->string, b->string);
return a->count - b->count;
}
void string_count_pint(struct string_count* sc) {
int i;
qsort(sc->entries, sc->nb_string, sizeof(struct string_count), Compare);
i = 0;
while (i < sc->nb_string) {
printf("%d %s\n", sc->entries[i].count, sc->entries[i].string);
i ;
}
}
void string_count_free(void* pt) {
struct string_count* sc = malloc(sizeof(pt));
char i;
for (i = 0; i < sc->nb_string; i ) {
free(sc->entries[i].string);
}
free(sc->entries);
}
char* readline(void) {
int i = 0;
char c;
char* linebuf = (char*)malloc(MAX_STRING);
while (read(0, &c, 1) != 0) {
if (c == '\n') {
linebuf[i] = '\0';
return linebuf;
}
linebuf[i ] = c;
}
return NULL;
}
void* thread_main(void* arg) {
struct string_count* sc = malloc(sizeof(arg));
char* line;
while ((line == readline()) != '\0') {
addstring(sc, line);
}
return NULL;
}
int main(int argc, char** argv) {
int nbthreads;
int i;
pthread_t threads[MAX_THREADS];
struct string_count* sc;
if (argc != 1) {
fprintf(stderr, "usage: %s <nb threads>\n", argv[0]);
return EXIT_FAILURE;
}
nbthreads = atoi(argv[1]);
sc = malloc(sizeof(nbthreads));
for (i = 0; i < nbthreads; i ) {
pthread_create(&threads[i], NULL, thread_main, sc);
}
do {
pthread_join(threads[nbthreads--], NULL);
} while (nbthreads > 0);
string_count_free(sc);
string_count_pint(sc);
return EXIT_SUCCESS;
}
CodePudding user response:
I suspect the bug is in this line: sc = malloc(sizeof(nbthreads));
You probably wanted sc = malloc(sizeof(string_count));
I'm also not sure if struct string_count* sc = malloc(sizeof(arg)); does what you intended in thread_main.
You probably need the sc in main be an array and pass a different item in it to each thread and then aggregate them after the join.
CodePudding user response:
Here are the first few errors I have spotted, in no particular order.
- Unprotected modification of data structures from multiple threads. Read something about multithreading. Pay attention to the word "mutex".
pthread_join(threads[nbthreads--], NULL);goes out of bounds.struct string_count* sc = malloc(sizeof(arg));makes no sense.sizeof(arg)is the size of a pointer (8 on most PC-like systems). This is not enough to hold onestruct string_count.struct string_count_entry* a = malloc(sizeof(pt2));apparently has even less sense. You are allocating something in a string comparison function, using a wrong size, then you are using the allocated memory without initializing it, and without even trying to compare the things passed to the function.while ((line == readline()) != '\0')does not assign anything.pt->entries = realloc(pt->entries, pt->nb_string 1 * sizeof(pt->entries[0]));is missing a couple of parentheses.
