0

My Windows program (compiled using MSYS2 MINGW64) outputs its stdout data in large blocks. A printf() call with a \n doesn't correctly flush the output.

As a variation of this question, under what conditions does printf() NOT flush?


As an example, the following code outputs in blocks on MSYS2 MINGW64:

#include <stdio.h>

int main() {
        while(1) {
                printf("test\n");
                Sleep(1);
        }
        return 0;
}
Xunie
  • 362
  • 2
  • 16
  • Please post the [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) with complete code that demonstrates the problem. – Weather Vane Apr 25 '20 at 13:45
  • 2
    According to [this answer](https://stackoverflow.com/a/4201325/10805404), it does not flush when encountering a newline (aka *line buffered*) if `stdout` is *fully buffered* (this is the case if it is not an interactive device, it could be a file for example). Also, this has actually nothing to to with `printf` but only with the stream. – Simon Doppler Apr 25 '20 at 13:53
  • 4
    Windows stdio doesn't do line buffering for output streams. – Shawn Apr 25 '20 at 13:54
  • 1
    @Xunie: it's not language-lawyering because it's not about the language. It's completely dependent on the execution environment (OS/shell). – rici Apr 25 '20 at 14:57

4 Answers4

3

On Windows there's no line buffering, only no and full buffering

  • _IOLBF
    • For some systems, this provides line buffering. However, for Win32, the behavior is the same as _IOFBF - Full Buffering.

setvbuf

Wait for a while until the buffer is full, or flush the buffer yourself. Alternatively you can decrease the buffer size with setvbuf() so that it flushes more frequently

phuclv
  • 27,258
  • 11
  • 104
  • 360
2

under what conditions does printf() NOT flush?

With mingw-w64, I am not aware, yet the behavior of mingw-w64 is not required to apply elsewhere. Code cautiously is only targeting one implementation.

The following applies to C, in general.

Typically if the printf() lacks a '\n', it does not flush, yet that is implementation defined behavior.

The conditions in which printf() flushes or does not is implementation defined. There are many possibilities. See What are the rules of automatic stdout buffer flushing in C

To insure stdout is flushed, follow with a fflush(stdout);.

chux - Reinstate Monica
  • 113,725
  • 11
  • 107
  • 213
1

It appears that in the msys2 shell running under mintty, at least for MINGW64, 'stdin', 'stdout' and 'stderr' all report 0 (false) for 'isatty()', whereas if you open a Windows CMD.EXE prompt and run the same executable, all three file descriptors (0, 1, and 2) return 1 (true).

I'm not convinced this has always been the behavior, as I'm pretty sure I never ran into this until I re-installed msys2.

This is not the correct behavior according to POSIX.1 [IEEE Std 1003.1-2017 (Revision of IEEE Std 1003.1-2008)], https://pubs.opengroup.org/onlinepubs/9699919799/

At program start-up, three streams shall be predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). When opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

My tests indicate that neither stdout nor stdin not fully buffered when running the msys2 bash shell in mintty.

Adding the following to the beginning of your "main()" does make stderr and stdout non-buffered:

   (void)setvbuf(stdout, NULL, _IONBF, 0);
   (void)setvbuf(stderr, NULL, _IONBF, 0);
-1

As an addition to the other answer you can do all your output in printf just don't do the \n and instead use cout << endl after it. That oughta flush the output.

Mahmood Darwish
  • 547
  • 3
  • 11