I've been working on this code for awhile now and I've run into a seg fault that I can't seem to debug. Here's the relevant code:
typedef struct Halo* Halo;
struct Halo
{
float x, y, z;
float vx, vy, vz;
int n200a;
float m200a;
float r200a;
int n200c;
float m200c;
float r200c;
int n500a;
float m500a;
float r500a;
int n500c;
float m500c;
float r500c;
};
Global variable:
Halo *halo_catalog;
The function that fails:
int loadHaloCatalog(char *filename)
{
FILE *catalog_file;
long long halo_num;
catalog_file = fopen(filename, "rb");
if (catalog_file == NULL) {
printf("Could not open halo catalog: %s\n", filename);
return -1;
}
if (fread(&halo_num, sizeof(long long), 1, catalog_file) < 0) {
printf("Could not read number of halos\n");
return -1;
}
halo_catalog = (Halo *)calloc(halo_num, sizeof(struct Halo));
if (fread(halo_catalog, sizeof(struct Halo), halo_num, catalog_file) < 0) {
printf("Could not read that number of halos\n");
return -1;
}
printf("%f\n", halo_catalog[10000]->x);
printf("done\n");
fclose(catalog_file);
return (int)halo_num;
}
It fails on the "printf("%f\n", halo_catalog[10000]->x);" line, or any other access to the memory that is allocated after the fread call. I know that I am passing in a valid file, as it can read halo_num correctly. It also collects the correct about the Halo objects from the fread call, as when I call fread and check the return it returns halo_num.
Thanks!
typedef struct Halo* Halo;
That's a terrible idea, and probably the cause of your problems.
You have a global variable
Halo *halo_catalog;
so a struct Halo**
. But in
halo_catalog = (Halo *)calloc(halo_num, sizeof(struct Halo));
if (fread(halo_catalog, sizeof(struct Halo), halo_num, catalog_file) < 0) {
you use it as if it were a struct Halo*
.
Then you index
printf("%f\n", halo_catalog[10000]->x);
at a distance of 10000 * sizeof(struct Halo*)
bytes from where halo_catalog
points, and interpret the bytes at that location - which are part of the values of some float
s or int
s read in, not pointers - and try to access the x
component of whatever arbitrary location was the result of that misinterpretation.
You should
typedef struct Halo Halo;
and use halo_catalog[10000].x
to fix that issue.
Another issue is that fread
returns the number of items it has successfully read, if that is smaller than the requested number, it can still be a positive number.
Capture the return value of fread
, and use that to determine whether the reading was completely successful. Also, be sure that 10000 is a valid index before trying to print halo_catalog[10000].x
.