-1

I'm working on a code which purpose is to manipulate a 1D array coming from a 3D array. Showing the code will explain everything:

First of all, I'm working with array of structures:

typedef struct range_in_memory {
      double E, R;
} RANGE;

And I wrote this function that works like a charm when called in simple debug implementation:

    RANGE *dq_Eloss_load_range_file (double Aion, double Zion, double Atar, double Ztar, int *n){

      char *filename;
      char errormsg[80], dummy;
      int N = 2;
      int i = 0;
      FILE *fp;
      RANGE *memrange;

      filename = (char*)malloc (50*sizeof (char));
      dq_Eloss_set_filename (filename, Aion, Zion, Atar, Ztar);  
      fp = dq_myfopen (filename, "r", errormsg);

      while ( !feof (fp) ){
        fscanf (fp, "%c", &dummy);

        if (dummy == '\n') {
          N++;

        }
      }

      rewind (fp);

      memrange = (RANGE*) calloc (N, sizeof (RANGE));

      while ( !feof (fp) ){
        fscanf (fp, "%lf\t%lf\n", &memrange[i].E, &memrange[i].R);
        i++;
      }
      *n = N;

    //   for (i=0; i<N; i++){
    //         printf ("\n%lf  %lf", memrange[i].E, memrange[i].R);
    //   }

      fclose (fp);

      return (memrange);
}

The commented for cycle is crucial, so keep it in mind. Now, coming to my problem, I need to use a 3D array like:

RANGE ***memrangeTAR;

The function *dq_Eloss_load_range_file loads the content of a file int an array of RANGE type. I want to do this for several files, which are named according to two parameters Aion and Zion. In my mind it would have been something like:

(double) memrangeTAR [Aion][Zion][i].E
(double) memrangeTAR [Aion][Zion][i].R

which would have been the values in the i-th line in the file related to Aion and Zion.

This is the code:

void dq_load_range_files (RANGE ***memrangeTAR){
  int NTAR;
  double *ZMAX;
  int Aion, Zion, AMAX = 250.;
  int i;



  printf ("\n   Allocating Memory for range data..."); fflush (stdout);
  ZMAX = (double*) malloc ((AMAX+1)*sizeof (double));
  memrangeTAR   = (RANGE***) malloc ((AMAX+1)*sizeof (RANGE**));


  for (Aion=1; Aion<=AMAX; Aion++){
    ZMAX[Aion] = ceil (dq_range_table_get_max_Zion (Aion)); 
    memrangeTAR  [Aion] = (RANGE**) malloc ((ZMAX[Aion]+1)*sizeof(RANGE*)); 
  }

  printf ("   ...ALLOCATED!                                  \n\n");


  printf ("\n   Loading range data...\n"); fflush (stdout);

  for (Aion=1; Aion <=AMAX; Aion++){

        for (Zion=1; Zion<=ZMAX[Aion]; Zion++){

      memrangeTAR  [Aion][Zion] = dq_Eloss_load_range_file ((double)Aion, (double)Zion, cor_sosau16.mass.Mtar,  cor_sosau16.charge.Ztar,  &NTAR); 

//   for (i=0; i<N; i++){
//         printf ("\n%lf  %lf", memrangeTAR[Aion][Zion][i].E, memrangeTAR[Aion][Zion][i].R);
//   }   

    }
  }

}

It compiles (gcc on unix machine using gnu99 standard). It runs unless i try to access to the 3D array. If I de-comment the printing cycle in the first function, I can get what I want: it prints on terminal the content of the current file. If I de-comment the for cycle in the second function, it gives me segmentation fault.

What am I doing wrong?

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • First please read [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). Secondly, please read [Do I cast the result of malloc?](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Thirdly, why do you allocate memory for `filename`? Lastly, *where* do you get the crash? On what line? Please mark it out with e.g. a comment. And if you don't know, then learn how to use a debugger to catch crashes in action. – Some programmer dude Mar 15 '17 at 16:53
  • 3
    There is no 3D array in your code. And being a 3-star C programmer is not a compliment. Using `***` is almost always a signal of bad code. – too honest for this site Mar 15 '17 at 16:53
  • do an allocation of a real 3D with something as `mytype (*X)[a][b] = malloc(sizeof(mytype[n][a][b]));`. – Jens Gustedt Mar 15 '17 at 18:20
  • I read the two articles and understood the, I shall improve my code on that side easily. Filename is allocated because of the needs of the function dq_Eloss_set_filename. It could be done better but is not related to the main error. I shall seek however a way to improve it. Coming to the error it happens after calling the function dq_Eloss_load_range_file.. if i print or use in any way the variables memrangeTAR[Aion][Zion][i].E or memrangeTAR[Aion][Zion][i].R – Danio Quero Mar 15 '17 at 18:32

1 Answers1

0

I somehow managed to solve but not to understand WHY it's a solution. By defining a

RANGE *tmp;

variable, calling the usual function as

tmp = dq_Eloss_load_range_file ((double)Aion, (double)Zion, cor_sosau16.mass.Mtar, cor_sosau16.charge.Ztar, &NTAR);

and then assigning wanted pointer:

memrangeTAR[Aion][Zion] = tmp;

I can use the content of the variables in any way now, like:

   for (i=0; i<N; i++){
        printf ("\n%lf  %lf", memrangeTAR[Aion][Zion][i].E, 
                              memrangeTAR[Aion][Zion][i].R);
   } 

In this way no segmentation fault error is encountered, making me think that the problem was the way I was passing the pointer to the function, but still don't understand...