Search code examples
cpointersiosegmentation-faultmalloc

Why am I getting a seg fault every time I try to store elements into an array in C?


So, I am trying to read a matrix from a file and store it into an array.

The matrix files are as follows:

2 3
1 5 8
6 3 9

With the first two digits on the first line representing Rows x Columns.

I seem to be getting an issue whenever I try to store something into my array, as I am able to simply reprint everything to the screen, but I am seg faulting whenever I try to add to an array.

My code is as follows:

double *read_matrix(char *filename){
     FILE *file=fopen(filename, "r");
 
     if(!file){
         fprintf(stderr, "An error has occurred. Wrong file name?\n");
         exit(errno);
     }

     double *data=(double *)malloc(sizeof(double)*4096);
     char *buff=malloc(sizeof(char *)*256);
     char *curr;

     while(fgets(buff,sizeof(buff),file)){
         curr=strtok_r(buff," ",&buff);
         int i=0;
         while(curr!=NULL){
             curr=strtok_r(NULL," ",&buff);
             data[i]=strtod(curr,NULL); //this
             i++;
         }
     }
     return data;
}

Whenever I debug with GDB and use the backtrace command, it brings me to the line with comment //this.

I am having troubles understanding what I have done wrong, and I'm starting to go mad!


Solution

  • This

         while(curr!=NULL){
             curr=strtok_r(NULL," ",&buff);
             data[i]=strtod(curr,NULL); //this
             i++;
         }
    

    should be

         while(curr!=NULL){
             data[i]=strtod(curr,NULL); //this
             i++;
             curr=strtok_r(NULL," ",&buff);  // Looking for next token shall 
                                             // be the last statement
         }
    

    Further this line

    char *buff=malloc(sizeof(char *)*256);
    

    is wrong. It should be

    char *buff=malloc(sizeof(char)*256);
                             ^^^^
                             No *
    

    But in general for your malloc it's much better to use the form:

     double *data = malloc(4096 * sizeof *data);
                                  ^^^^^^^^^^^^
    
     char *buff=malloc(256 * sizeof *buff);
                             ^^^^^^^^^^^^
    

    By using sizeof *varname you avoid simple type mismatches as the one you had.