Search code examples
clinuxfwritefread

Strange value when reading from binary file with fread() in C


I have an issue that I can't solve...

I used fwrite to write an int value (among other values that come from a struct) into a file that I've opened using fopen(file, "wb");

This worked fine, and when I view the contents of the file, I can see the HEX value of the int that I've "written" (and all the other values as well).

Next, I try to read the file. So, I open the file using fopen(file, "rb"); and start reading it using fread. The first int value is read correctly (e.g. 7) and all the other values after it - which belong to the first struct that I've written.

I then try to read the next struct and when I try to read the first int value, I receive a very strange number (e.g. 1140850688) but it should be 39 instead.

So the question is: Why is this happening? And how can I solve it?

My struct looks like this:

struct a {
    int a1;
    char* a2;
    struct b* a3;
    unsigned char a4; 
    int a5;
    char* a6; 
}

And the fread call looks like this: fread(&(tmpA->a1), sizeof(int), 1, file);

EDIT:

The fwrite part:

fwrite(&(tmpA->a1), sizeof(int), 1, file);
fwrite(tmpA->a2, sizeof(char), strlen(tmpA->a2), file);
fwrite(tmpA->a3, sizeof(struct b), 1, file);
fwrite(&(tmpA->a4), sizeof(unsigned char), 1, file);
fwrite(&(tmpA->a5), sizeof(int), 1, file);
fwrite(tmpA->a6, sizeof(char), strlen(tmpA->a6), file);

The fread is almost the same.


Solution

  • I suspect your problem is on this line

    fwrite(tmpA->a3, sizeof(struct b), 1, file);
    

    where you are writing a struct. This struct will have padding bytes, as per this wikipedia article which will offset the rest of your data. You will likely have to come up with a better way of writing that struct to memory. This page provides additional explanation.

    You can check to see if this is indeed the problem by checking if a4 has the value you expect, or by comparing the size of the entire struct versus the sum of the sizes of its members.

    Also, these lines look dangerous:

    fwrite(tmpA->a2, sizeof(char), strlen(tmpA->a2), file);
    fwrite(tmpA->a6, sizeof(char), strlen(tmpA->a6), file);
    

    they say that the length of the string being printed may vary in your stored data. strlen will give you the length of your string without counting the terminating \0 so there is no good way to know where a string ends once you've written it. I can't imagine how you plan on reading the string back in.