Why does fread() not work here when trying to read 8 bytes? (C Programming)

83 views Asked by At

I am trying to use fread() to pass the contents of a file to a function that takes 8 bytes at a time, and measure how long it takes to go from start to end, calling and passing arguments to said function every 8 bytes.

I have been able to make this work when reading in 1 byte at time, and passing the byte to 'functionX' which takes 1 byte as an argument with an input parameter as "(const char *str)".

    FILE *fp = fopen(argv[1], "r");
    char *buffer;
    //Begin timer
    while (((fread(&buffer, 1, 1, fp)) != 0)) {
        functionX(buffer);
    }
    //End timer
    fclose(fp);

I also need to do the same thing, but instead read (and pass) 8 bytes at a time, to 'functionY' which has the same input parameter as functionX but is made to be passed 8 bytes at a time. However, when I try to do this, it results in a segmentation fault, and I am unsure why.

    //The buffer declaration in previous code segment is the same 
    //variable used here, I just didn't copy over that statement
    FILE *fp2 = fopen(argv[1], "r");
    //start timer
    while (((fread(&buffer, 8, 1, fp2)) != 0)) {
        functionY(buffer);
    }
    //end timer
    fclose(fp2);

I am not sure why this is happenning, I'm assuming that my understanding of how fread() works is where the issue is, but not sure specifically why.

2

There are 2 answers

0
rslemos On

You should declare your buffer as char[1] (or char[8] in the second case).

Also you'll have to pass the buffer address without &.

The way you did, the space allotted to your buffer is enough just to hold a pointer to char (which explains why your first case worked indeed, though this mixing of pointer and char storage still should be regarded as undefined behavior).

0
chux - Reinstate Monica On

Use fread() properly.

  • Pass to fread() the address of the array's first element, not the address of the array.*1

  • Pass to fread() the size of an array element and then the number of array elements.

  • Checking against 0 it not so good here. Better to check against the expected number of elements read.

  • Extra () removed.

Fixed size buffer

    #define BUF_N 42 /* or whatever positive value you want */
    // char *buffer;
    char buf[BUF_N];

    // while (((fread(&buffer, 1, 1, fp)) != 0)) {
    while (fread(buf, sizeof buf[0], BUF_N, fp) == BUF_N) {

Allocated buffer

    #define BUF_N 42 /* or whatever positive value you want */
    // char *buffer;
    char *buf = malloc(sizeof buf[0] * BUF_N);
    if (buf == NULL) {
      ; // TBD code to handle error
    }

    // while (((fread(&buffer, 1, 1, fp)) != 0)) {
    while (fread(buf, sizeof buf[0], BUF_N, fp) == BUF_N) {

    ...

    free(buf);  // Do not forget to free allocated memory.

sizeof buf[0] is 1 when the array element type is char. Coded as sizeof buf[0] to allow the array type to change, say to int, without obliging other code to change.

*1
With char buf[BUF_N], the use of buf in fread(buf, ... does pass the array to the function, yet in this usage, the array is converted to a pointer to the type of first element - as needed here.