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

1

0

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);
}
Bonaventure answered 7/3, 2019 at 7:36 Comment(15)
why do you think that discarding buffered data prevents the buffer from being filled again ?Fulton
Such an fflush behavior is specific to Linux. Why don't you use ungetc?Idyllic
@SanderDeDycker I don't know about that.. So the discarded part of data will be read into the buffer again? Let's say I have 123456 in file, buffer is 3, for the first time it reads 123 into the buffer and somehow dicard the buffer, will the system read 456 next time or start from the beginning again, which still reads 123? ThanksBonaventure
@BasileStarynkevitch Hmmm. I use getc to test if the buffer is discarded or not. Why use ungetc?Bonaventure
@Bonaventure : if at the moment of the flush, the buffer holds "123" (not yet read by your application), and nothing else happens to the input stream, a subsequent read should fill the buffer again starting with "123..."Fulton
can you clarify what you're asking exactly ? Are you trying to understand why the behavior doesn't match your expectation ? Or are you trying to get the behavior to match your expectation ?Fulton
@SanderDeDycker ..If that's what happen under the hood, then the result can make sense... Hmmm give me a few mins to think about it.Bonaventure
@Bonaventure how do you know what was buffered and what remains in the file, to know whether the buffer data was discarded?Klaxon
@SanderDeDycker I do what the manpage says but I think I don't get the expected result. So I am doubting if the manpage is wrong, now you tell me that I do not understand what happen correctly.Bonaventure
@WeatherVane I use CLion to debug, examining the _IO_read_ptr and _IO_read_end pointers to see what was buffered. I don't know whether the buffer data was dicarded, the manpage says so and I just believe it (cause I don't know how it internally works), but I don't know how the next read will operate, starts before discarded place, or starts after discarded position, that what I don't know.Bonaventure
It should work more like what you expect if you use stdin instead of fp. Then you can type something on the keyboard and press enter. If the code does a few reads and calls fflush(stdin), the rest of the line should be discarded.Obelize
I don't even see the point of using fflush on a disk file (that is not still being written to). It only makes sense to me as user3386109 to clear out unwanted keyboard input: for example if you have asked an important question and you want to ensure there is no type-ahead buffered.Klaxon
@WeatherVane Yes, the question itself it's not very meaningful indeed... But I was told that the system read before the discarded position after fflush(), which correct my understanding..Bonaventure
@SanderDeDycker You can write it down as an answer and I would like to mark it :). A little bit more explanation is much appreciated.Bonaventure
If your program always reads from the terminal (without redirection from files or pipes) consider using readlineIdyllic
F
2

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).

Fulton answered 7/3, 2019 at 8:53 Comment(1)
Hey dear Dycker, would you like to help me with this https://mcmap.net/q/2037268/-usage-of-fmemopen if you have time? It's an example from Advanced Programming in the UNIX® Environment.Bonaventure

© 2022 - 2024 — McMap. All rights reserved.