0

Hi this is the multithread program I'm trying to write but it gives me segfault
the original code works fine without multi-thread but this gives me segfaults
I used mutex in every global var reading but even one thread gives me segfault
this is my multithreaded code that segfaults

# include <stdio.h> 
# include <string.h> 
# include <pthread.h>
# include <stdlib.h>
# include <math.h>
# include <limits.h>

# define NUMBER_OF_COLUMNS 20
# define NUMBER_OF_CLASSES 4
# define NUMBER_OF_THREADS 4
# define NUMBER_OF_COLUMNS_PLUS_ONE 21 //STUPID C WONT LET ME MAKE GLOBAL VECTORS
double max[NUMBER_OF_COLUMNS], min[NUMBER_OF_COLUMNS];
double maxMinusMin[NUMBER_OF_COLUMNS];
int number_of_datas = 0, number_of_wrong_predictions = 0;
pthread_t threads[NUMBER_OF_THREADS];
pthread_mutex_t mutex_minmax;


void * solve(void *id){
    FILE *traincsv, *weightscsv;
    long tid;
    tid = (long) id;
    char buffer[1024];
    char* token;
    int EOFchecker = 1;
    double temp;
    double sum[NUMBER_OF_CLASSES];
    double vectors[NUMBER_OF_CLASSES][NUMBER_OF_COLUMNS_PLUS_ONE];
    int winner = 0;
    int number_of_datas_local = 0, number_of_wrong_predictions_local = 0;
    char filename[16];
    sprintf(filename, "trainq%ld.csv", (tid + 1));
    printf("Hello World! Thread ID, %ld\n", tid);
    printf("%s\n", filename);
    traincsv = fopen(filename,"r");
    weightscsv = fopen("weights.csv","r");


    //load vectors to array last one is bias
    pthread_mutex_lock(&mutex_minmax);
    fscanf(weightscsv,"%s",buffer);//first junk line
    for (size_t i = 0; i < NUMBER_OF_CLASSES; i++)
    {
        fscanf(weightscsv,"%s",buffer);
        token = strtok(buffer,",");
        for (size_t j = 0; j < NUMBER_OF_COLUMNS + 1; j++)
        {
            temp = atof(token);
            vectors[i][j] = temp;
            token = strtok(NULL,",");//next token of last string
        }
    }
    pthread_mutex_unlock(&mutex_minmax);
    pthread_mutex_lock(&mutex_minmax);
    fscanf(traincsv,"%s",buffer);//first line is just names
    fscanf(traincsv,"%s",buffer);
    pthread_mutex_unlock(&mutex_minmax);
    while (EOFchecker != EOF)
    {
        token = strtok(buffer,",");
        //reset sum of wieghts to bias;
        printf("thread id %ld token %s\n",tid,token);
        for (size_t i = 0; i < NUMBER_OF_CLASSES; i++)
        {
            sum[i] = vectors[i][NUMBER_OF_COLUMNS];
        }
        for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
        {
            temp = atof(token);

            //Normalize
            pthread_mutex_lock(&mutex_minmax);
            temp = (temp-min[i])/(maxMinusMin[i]);
            pthread_mutex_unlock(&mutex_minmax);

            for (size_t j = 0; j < NUMBER_OF_CLASSES; j++)
            {
                sum[j] += vectors[j][i] * temp;
            }
            token = strtok(NULL,",");//next token of last string
        }
        //check which vector has most points
        for (size_t i = 0; i < NUMBER_OF_CLASSES; i++)
        {
            if (sum[i] > sum[winner])
            {
                winner = i;
            }
            
        }
        if(winner != atof(token)){
            number_of_wrong_predictions_local ++;
        }
        number_of_datas_local ++;
        pthread_mutex_lock(&mutex_minmax);
        EOFchecker = fscanf(traincsv,"%s",buffer);
        pthread_mutex_unlock(&mutex_minmax);
    }
    pthread_mutex_lock(&mutex_minmax);
    number_of_datas+=number_of_datas_local;
    number_of_wrong_predictions+=number_of_wrong_predictions_local;
    pthread_mutex_unlock(&mutex_minmax);
    pthread_exit(NULL);
}
int main(){
    void * status;
    FILE *traincsv, *traincsvnorm, *weightscsv;
    char buffer[1024];
    char* token;
    double temp;
    int EOFchecker = 1;
    int return_code;
    
    
    if (pthread_mutex_init(&mutex_minmax, NULL) != 0) { 
        printf("\n mutex init has failed\n"); 
        return 1; 
    } 
    
    for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
    {
        min[i] = INFINITY;
    }
    
    
    traincsv = fopen("train.csv","r");
    traincsvnorm = fopen("trainnorm.csv","w+");

    // find min and max
    fscanf(traincsv,"%s",buffer);//first line is just names
    fscanf(traincsv,"%s",buffer);
    while (EOFchecker != EOF)
    {
        token = strtok(buffer,",");
        for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
        {
            temp = atof(token);
            if(max[i]<temp) max[i] = temp;
            if(min[i]>temp) min[i] = temp;
            token = strtok(NULL,",");//next token of last string
        }
        EOFchecker = fscanf(traincsv,"%s",buffer);
    }
    for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
    {
        maxMinusMin[i] = max[i] - min[i];
    }
    for(long tid = 0; tid < NUMBER_OF_THREADS; tid++)
    {
        return_code = pthread_create(&threads[tid],
                NULL, solve, (void *) tid);

        if (return_code)
        {
            printf("ERROR; return code from pthread_create() is %d\n",
                    return_code);
            exit(-1);
        }
    }

    // pthread_mutex_destroy(&mutex_minmax);
    printf("wrong predictions : %d \nall predictions : %d \n",number_of_wrong_predictions,number_of_datas);
    for(long i = 0; i < NUMBER_OF_THREADS; i++)
        pthread_join(threads[i], &status);
    fclose(traincsv);
    fclose(traincsvnorm);
    pthread_exit(NULL);
}

this is my original code that works fine

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

# define NUMBER_OF_COLUMNS 20
# define NUMBER_OF_CLASSES 4
// void * solve(void *id){
//     int tid;
//     tid = (int) id;

// }
int main(){
    FILE *traincsv, *traincsvnorm, *weightscsv;
    char buffer[1024];
    char* token;
    double temp, max[NUMBER_OF_COLUMNS], min[NUMBER_OF_COLUMNS];
    int EOFchecker = 1;
    int number_of_datas = 0, number_of_wrong_predictions = 0;
    double vectors[NUMBER_OF_CLASSES][NUMBER_OF_COLUMNS + 1];
    double sum[NUMBER_OF_CLASSES];
    int winner = 0;

    for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
    {
        min[i] = INFINITY;
    }
    
    
    traincsv = fopen("train.csv","r");
    traincsvnorm = fopen("trainnorm.csv","w+");
    weightscsv = fopen("weights.csv","r");
    // fprintf(traincsvnorm,"%s\n",buffer);

    //load vectors to array last one is bias
    fscanf(weightscsv,"%s",buffer);//first junk line
    for (size_t i = 0; i < NUMBER_OF_CLASSES; i++)
    {
        fscanf(weightscsv,"%s",buffer);
        token = strtok(buffer,",");
        for (size_t j = 0; j < NUMBER_OF_COLUMNS + 1; j++)
        {
            temp = atof(token);
            vectors[i][j] = temp;
            token = strtok(NULL,",");//next token of last string
        }
    }

    //find min and max
    fscanf(traincsv,"%s",buffer);//first line is just names
    fscanf(traincsv,"%s",buffer);
    while (EOFchecker != EOF)
    {
        token = strtok(buffer,",");
        for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
        {
            temp = atof(token);
            if(max[i]<temp) max[i] = temp;
            if(min[i]>temp) min[i] = temp;
            token = strtok(NULL,",");//next token of last string
        }
        EOFchecker = fscanf(traincsv,"%s",buffer);
    }
    // Normilize
    double maxMinusMin[NUMBER_OF_COLUMNS];
    for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
    {
        maxMinusMin[i] = max[i] - min[i];
    }
    EOFchecker = 1;
    fseek(traincsv,0,SEEK_SET);
    fscanf(traincsv,"%s",buffer);//first line is just names
    fscanf(traincsv,"%s",buffer);
    while (EOFchecker != EOF)
    {
        token = strtok(buffer,",");
        //reset sum of wieghts to bias;
        for (size_t i = 0; i < NUMBER_OF_CLASSES; i++)
        {
            sum[i] = vectors[i][NUMBER_OF_COLUMNS];
        }
        for (size_t i = 0; i < NUMBER_OF_COLUMNS; i++)
        {
            temp = atof(token);
            temp = (temp-min[i])/(maxMinusMin[i]);
            for (size_t j = 0; j < NUMBER_OF_CLASSES; j++)
            {
                sum[j] += vectors[j][i] * temp;
            }
            token = strtok(NULL,",");//next token of last string
        }
        //check which vector has most points
        for (size_t i = 0; i < NUMBER_OF_CLASSES; i++)
        {
            if (sum[i] > sum[winner])
            {
                winner = i;
            }
            
        }
        if(winner != atof(token)){
            number_of_wrong_predictions ++;
        }
        number_of_datas ++;
        EOFchecker = fscanf(traincsv,"%s",buffer);
    }

    printf("wrong predictions : %d \nall predictions : %d \n",number_of_wrong_predictions,number_of_datas);
    fclose(traincsv);
    fclose(traincsvnorm);
    fclose(weightscsv);
}

these are inputs train.csv weights.csv
it somtimes gives me free(): invalid pointer error and also here is gdb bt

  • In general, do not use `strtok()`. (see also my answer to this question: https://stackoverflow.com/questions/15472299/split-string-into-tokens-and-save-them-in-an-array/65107407#65107407 ) – 12431234123412341234123 Dec 21 '20 at 12:32

1 Answers1

0

found it strtok is not reentrant, so it's thread unsafe. On POSIX environment, usestrtok_r instead.