Search code examples
clinuxfflush

Why fflush(input_filestream) does not discard buffer on linux as manpage describes?


man fflush on Ubuntu:

For input streams associated with seekable files (e.g., disk files, but not pipes or terminals), fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application.

I've read some questions talking about fflush(stdin) and fflush() a input stream is undefined behaviour according to the standard, that's right. But for Linux specifically, I've read comments says that it's not a undefined behaviour but an extension, yes, the manpage above says how it would work on a file input stream.

So, why fflush() a input filestream does not discard buffered data that has been fetched from the underlying file, but has not been consumed by the application. as the manpage describes ?

Before searching on the Web I fully believe the manpage now I want to know if it's wrong.


Sample code:

haha2.txt: 123456, no line feed or whitespace.

#include <stdio.h>

int
main()
{
    FILE* fp = fopen("haha2.txt", "r");
    int q = getc(fp);
    fflush(fp);
    int j = getc(fp); // I expect the rest variables to be -1(EOF) starting from here
    int j2 = getc(fp);// But they can still read data as if fflush does not executed
    int j3 = getc(fp);
    int j4 = getc(fp);

    int j5 = getc(fp);
    int j6 = getc(fp);
    int j7 = getc(fp);
    int j8 = getc(fp); 
    printf("%c,%c,%c,%c,%c,%c,%c,%c\n", j,j2,j3,j4,j5,j6,j7,j8);
    return(0);
}

Solution

  • Flushing the file buffer only discards the data from the buffer. It doesn't impact the file's contents. Subsequent reads will just keep reading the file as if nothing happened (except that the buffer first has to be filled again).

    Of course, this assumes that nothing happened to the file in the meantime (eg. some other process overwriting part of the file, truncating it, etc.).

    To illustrate, if you modify your code to include a sleep after the fflush :

    #include <stdio.h>
    #include <unistd.h>
    
    int main() {
        FILE* fp = fopen("haha2.txt", "r");
        int q = getc(fp);
        fflush(fp);
        sleep(10);
        int j = getc(fp); // I expect the rest variables to be -1(EOF) starting from here
        printf("%d\n", j);
        return(0);
    }
    

    When you run this code, and in another terminal, you run this command during the sleep (this command will remove all contents from the file and set its size to 0) :

    truncate -s0 haha2.txt
    

    Then the code will print -1 (because the end of the file has been reached).

    If you try the same again (make sure to add your test data back into the file first), but this time without the fflush, the code will print the second character in the file, because the start of the file was still buffered (even though the actual file no longer contains anything).