Question

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!

Was it helpful?

Solution

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 floats or ints 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.

OTHER TIPS

Does that actually compile?

The issue is that halo_catalog is a pointer to an array, not an array of pointers. You should be using printf("%f\n", halo_catalog[10000].x);

I'm assuming the 10000 is just for testing purposes? Because there's nothing I saw that guarantees there are 10000 records in the halo_catalog.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top