dsal3389
dsal3389

Reputation: 710

c while loop keep running even when condition is false

I have written this code to play around with files, its reading a file in chunks of 256 byte

#include <stdio.h>
#include <stdlib.h>

#define CHUNK_SIZE 256


int chunkable(size_t size, int chunk_size){
    return (size - chunk_size) > 0;
}

char * read_file(FILE *f, size_t fsize){
    char * fbuff = (char *) malloc(sizeof(char) * fsize);

    if(chunkable(fsize, CHUNK_SIZE)){
        while(fsize > 0){
            printf("reading chunk..., remaining: %d\n", fsize);
            fread(fbuff, CHUNK_SIZE, 1, f);
            fsize -= CHUNK_SIZE;
        }
    } else {
        fread(fbuff, CHUNK_SIZE, 1, f);
    }
    return fbuff;
}

int main(int argc, char *argv[]){
    FILE * f;
    int fsize;
    char * file_content;

    if(argc == 1){
        fprintf(stderr, "argument missing (filename) exiting...\n");
        return -1;
    }

    f = fopen(argv[1], "r");
    if(f == NULL){
        fprintf(stderr, "couldent open %s, exiting...\n", argv[1]);
        return -1;
    }
    
    fseek(f, 0, SEEK_END);
    fsize = ftell(f);
    fseek(f, 0, SEEK_SET);

    file_content = read_file(f, fsize);
    printf("file content: %s\n", file_content);
    
    free(file_content);
    fclose(f);
}

the problem I have its with this line

while(fsize > 0){...}

every time a chunk is read from a file it subtract the chunk size from the remaining bytes to read, the while loop suppost to stop the read when there are no remaining bytes to read, but the output i am getting is

reading chunk..., remaining: 580
reading chunk..., remaining: 324
reading chunk..., remaining: 68
reading chunk..., remaining: -188
reading chunk..., remaining: -444
reading chunk..., remaining: -700
reading chunk..., remaining: -956
reading chunk..., remaining: -1212
reading chunk..., remaining: -1468
etc...

the fsize is a negative number which means fsize > 0 is false but the while loop keeps going 4ever

Upvotes: 1

Views: 62

Answers (1)

dbush
dbush

Reputation: 223689

size is of type size_t which is an unsigned type. So as you continue to subtract CHUNK_SIZE from size, the value wraps around to a very large positive value.

The reason you see a negative value when you print is because you're using the wrong format specifier to printf. %d expects an int argument. You should be using %zu instead for size_t.

You're also not checking the return value of fread. You could be reading less than CHUNK_SIZE bytes, or you could be getting an error. You also read into the same buffer every time, overwriting what was previously there.

You need to capture the return value and check it. Based on that, you subtract from size and also add an offset to fbuff to append to what you've already read.

    char *p = fbuff;
    while(fsize > 0){
        printf("reading chunk..., remaining: %zu\n", fsize);
        size_t len = fread(p, CHUNK_SIZE, 1, f);
        if (len == 0) {
            printf("error reading\n");
            break;
        }
        fsize -= len;
        p += len;
    }
    *p = 0;  // null terminate the string for printing

Upvotes: 4

Related Questions