1

I tried to scan some coordinates [X, Y, Z] from a file, but always returned as segmentation fault. So, I've some questions to make:

  1. I don't know how many points are in the file, but if I leave the struct arrays empty, there will be an error. There is a way to do this without defining a max number?

  2. Are my use of pointers ok? I'm not very talented with them.

I think that what is causing the segmentation fault is the fscanf, but I can't fix it

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define MAX 20000

FILE *f1;

struct points{
  int       n;
  float x[MAX];
  float y[MAX];
  float z[MAX];
};

int main (){

  int i;
  struct points cart1[MAX];
  f1 = fopen("point_cloud1.txt", "r");
  if (f1 == NULL){
    printf("Error Reading File\n");
    exit (0);
  }
  for(i = 0; !feof(f1); i++){
    fscanf(f1, "%f%f%f", &cart1[i].x[i], &cart1[i].y[i], &cart1[i].z[i]);
  }
  (*cart1).n = i+1;
  printf("\nNumber: %d coord1: %f, %f, %f\n", (*cart1).n, (*cart1).x[0], (*cart1).y[0], (*cart1).z[0]);

  fclose(f1);

return 0;
}

The beginning of the file is like this:

2.84838 -1.21024 -0.829256
7.09443 -3.01579 0.134558
3.31221 -1.40868 -0.830969
7.09813 -3.01883 0.404243
4.05924 -1.72723 -0.857496
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 4
    1) `for(i = 0; !feof(f1); i++){` :: feof() is wrong 2) why are you allocating 3*MAX*MAX items ? 3) `20000*20000*something` probably doesn't fit on the stack. – wildplasser Nov 22 '17 at 13:27
  • `(*cart1).n = i+1;` changes the first struct only. – Jean-François Fabre Nov 22 '17 at 13:28
  • 1
    The `struct points cart1[MAX]` array is huge. It's an array of 20000 points, and each point has 60000 floats. That's over 4 gigabytes. Are you sure you intended this? – Jabberwocky Nov 22 '17 at 13:30
  • if the x,y,z coordinates belong together, it would probably make more sense to have an array of structs, and not a struct of arrays – Karsten Koop Nov 22 '17 at 13:30
  • @wildplasser thanks for the quick answer. why is the feof() part wrong? 2) that was it, no more segmentation fault – Luis Parente Nov 22 '17 at 13:32
  • https://stackoverflow.com/q/5431941/905902 <<-- Read here. – wildplasser Nov 22 '17 at 13:37
  • If you have an error opening a file, then "Error Reading File" is a very misleading (and unhelpful) message. `if( (fp=fopen(path,mode)) == NULL) { perror(path); ...` – William Pursell Nov 22 '17 at 13:37
  • 1
    Maybe you should tell us in plain english what you are _actually_ trying to do. Please [edit] your question and make that clear _there_ – Jabberwocky Nov 22 '17 at 13:44

2 Answers2

1

You have a very large array declared as a local variable:

struct points cart1[MAX];

There are 20000 element in the array, and each array element is (assuming int and float each take up 4 bytes) 4 + 4 * 20000 + 4 * 20000 + 4 * 20000 = 240004 bytes for a total size of 4,800,080,000 ( 4.8 GB ). Even as a global variable, that's huge. As a local, which on most implementations lives on the stack, this easily exceeds stack size which results in the core dump.

You don't need an array of these structures, only a single one. Then you use it like this:

int main (){

  int i, r;
  struct points cart1;
  f1 = fopen("point_cloud1.txt", "r");
  if (f1 == NULL){
    printf("Error Reading File\n");
    exit (0);
  }
  for(i = 0, r = 3; r == 3; i++){
    r = fscanf(f1, "%f%f%f", &cart1.x[i], &cart1.y[i], &cart1.z[i]);
  }
  cart1.n = i+1;
  printf("\nNumber: %d coord1: %f, %f, %f\n", cart1.n, cart1.x[0], cart1.y[0], cart1.z[0]);

  fclose(f1);

return 0;
}

Also, don't use feof

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thank you, it solved the problem. But now I have only one question. By not using EOF, for will continue to execute until the return of fscanf `r != 3`. And when the file ends, it will execute one more time `r = 0` and then ends the for, right? – Luis Parente Nov 22 '17 at 14:04
  • @LuisParente That is correct. When the end of the file is reached `r` will be 0 and the loop will end. So when setting the count, you should actually use `i-1` instead of `i+1`. Note also that you had to do the same with `feof`. – dbush Nov 22 '17 at 14:06
  • Yes, i understand now. Before i was not getting any feedback, and that was not visible. About the first question, if I didn't know about the number of coordinates, how could i use the arrays without the MAX? Is it not possible? – Luis Parente Nov 22 '17 at 14:12
0
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define MAX 20000


struct point {          /* structure for *one* point */
  int       n;
  float x;
  float y;
  float z;
};

int main (void){

  FILE *f1;
  int ii;
  char *name="point_cloud1.txt";
  struct point  points[MAX];    /* array of MAX structures, for MAX points */

  f1 = fopen(name, "r");
  if (f1 == NULL){              /* diagnostics to stderr, add relevant detail, such as the filename */
    fprintf(stderr, "Error Reading File:%s\n", name);
    exit (0);
  }

  for(ii = 0; ii < MAX ; ii++){ /*loop-sanity: test the array-bounds where you increment it */
    int ret;
    ret = fscanf(f1, "%f%f%f", &points[ii].x, &points[ii].y, &points[ii].z); /* use the return value */
    if(ret<3) {
        if( !feof(f1)) fprintf(stderr, "Reading %s failed at %d\n", name, ii);
        break;
        }
  points[ii].n = ii+1;
  }

  if (ii == MAX && !feof(f1)) {
        fprintf(stderr, "Reading %s : array may be incomplete\n", name);
        }

  fclose(f1);

  printf("Number: %d coord0: %f, %f, %f\n", ii, points[0].x, points[0].y, points[0].z);

return 0;
}
wildplasser
  • 43,142
  • 8
  • 66
  • 109