Search code examples
cstructfreadunions

Structure is filled incorrectly during fread_s


I have the following structure defined ( u8 is typedef for unsigned char)

struct
{
    u8 length_directory_record;
    u8 extended_attribute_record;
    u8 location_of_extend[8];
    union
    {
        u8 bytes[8];
        struct
        {
            long little;
            long big;
        } endian;
    }
} dir;

Now when I read a file into this like this

fseek(myfile, (SECTOR_SIZE*222)+34+34, 0);
fread_s(&dir, sizeof(dir), sizeof(u8), 18, myfile);

I get weird large numbers when I print the data_length value (little one). The value actually are stored as LSB and MSB ( both byte orders), thats why I use the struct in the union.

printf("Data Length of File Section: %u\n", dir.data_length.endian.little);

However when I do the same steps without reading into a struct it works:

union{
    u8 val[4];
    long v;
} value;
fseek(myfile, ((SECTOR_SIZE * 222) + 34 + 34)+10, 0);
fread_s(&value, sizeof(value), sizeof(u8), 4, myfile);
printf("%u\n", value.v);

What is wrong with my first version? Why is the structure incorrectly filled or where is there any problem i do not see here ?

EDIT: Some more information: The file i am reading is a binary file. ((SECTOR_SIZE * 222) + 34 + 34) is the position where the structure starts. I verified this using a Hex Editor (Sector Size is 2048), so the +10 in the second example directly jumps to the offset of the 32bit number stored as LSB an MSB ( so 8 bytes)

File Dump of the offset starting the structure:

30 00 DF 00 00 00 00 00 00 DF 30 C3 0B 00 00 0B C3 30   0.ß......ß0Ã....Ã0

Expected value for the data_length is 770864 bytes but the output at the moment is 3862510 (random value)


Solution

  • This sort of problem often occurs with a structure packing mismatch. The junk between fields is likely due to the writer having 32-bit (or great) aligned fields when the fields themselves are not alignment size. What gets written in between? Random cruft.

    It's as if this declaration were in effect:

    #pragma pack (1)
    struct {
        u8 length_directory_record;
        u8 cruft_area_1[3];
        u8 extended_attribute_record;
        u8 cruft_area_2[3];
        u8 location_of_extend[8];
    
        ...