-1

I have wrote an binary file using c and checked it using xxd with following output:

6161 6161 6161 6161 6161 6161 6161 6161

Now my Code :

FILE * read;
    int * filebytes; 

    read = fopen("data/myfile","rb");

    fread(filebytes,4,4,read);

    for(int x = 0; x < var; x++){
        printf("%x\n",filebytes[x]);
    }
    fclose(read);

An im getting that output:

61616161
61616161
61616171
61616161

Now comes the even weirder thing, if i now not read out 4 times 32 bit but 5 times the last byte of the 3 row is not 71 but 75 ,reading out 6 times 32 bit 79 and so forth (every time adding 4). I cant think of a reason why that would happen every time at the 3th element im reading. I would like to know how to read out a file into 32 pieces and not getting weird changes into my code. Happy about every type of help.

qub3
  • 75
  • 7
  • ah btw changing int to uint32 doesnt change a thing. – qub3 Mar 06 '21 at 23:39
  • 1
    `filebytes` - Where have you allocated the memory? – Ed Heal Mar 06 '21 at 23:43
  • 2
    You're dereferencing an uninitialized pointer. That's undefined behavior. – Marco Bonelli Mar 06 '21 at 23:49
  • You're also playing with fire by hard-setting the `fread` item size to 4, which will be utterly wrong on some platforms. – WhozCraig Mar 06 '21 at 23:51
  • You should compile your program with warning flags turned on. `-Wall -Wextra` with gcc or clang, `/W4` with MSVC. See also [this question](https://stackoverflow.com/questions/3375697/what-are-the-useful-gcc-flags-for-c). – einpoklum Mar 06 '21 at 23:57

1 Answers1

3

"man fread" says this:

  #include <stdio.h>
  size_t fread(void *BUF, size_t SIZE, size_t COUNT, FILE *FP);

where:

        BUF - pointer to output memory
        SIZE - number of bytes in 1 "element"
        COUNT - number of 'elements' to read
        FP - open file pointer to read from

Here you have SIZE=4, COUNT=4, so you are trying to read 16 bytes.

But you are reading into memory location pointed to by filebytes - but this is currently just a random number, so could be pointing to anywhere in memory. As a result, your fread() command could:

  • end up crashing as the memory location 'filebytes' could point outside the address space
  • end up pointing to memory that other code will change later (eg as in your case)
  • just by sheer chance not be used by any other part of the code, and by luck work.

filebytes needs to point to valid memory, eg: on the heap: filebytes= (int *) malloc(16);

or on the stack, by making filebytes an local array to the function like: int filebytes[16];

Note that sizeof(int) might vary per machine/architecture, so "int filebytes[16] will allocate at least 16 bytes (as int will be at least 1 byte, normally a minimum of 2.)

(Note also that 'var' is not defined in your example - this should be defined. But even with var defined, this might not make sense:

for(int x = 0; x < var; x++){
printf("%x\n",filebytes[x]);
}

because you haven't said what you are trying to do. E.g. how many bytes in the input file represent 'one integer' ? This could be any number theoretically. And if say 4 bytes represent 'one integer' then is the most significant byte first, or the least significant byte first ? And note that your machine might be a big-endian or litte-endian machine, so for example if you run on a little-endian machine (least significant byte first), but your file has most-significant byte first, then loading directly into the integer array will not give the correct answer. Or even if they are the same, if you later run the same program on a different machine (with the opposite endian-ness), it will start breaking.

You need to decide:

  • how many bytes are in your integers in the file ?
  • are they most-significant byte first, or least significant byte first ? Then you could load into a 'unsigned char' array, and then manually build the integer from that. (That will work no matter endian of the machine.)
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
Fozzie
  • 52
  • 2