Why does stdout need explicit flushing when redirected to file?

后端 未结 3 547
鱼传尺愫
鱼传尺愫 2020-11-27 04:30

The behaviour of printf() seems to depend on the location of stdout.

  1. If stdout is sent to the console, then printf
3条回答
  •  执念已碎
    2020-11-27 05:12

    Your are wrongly combining buffered and unbuffered IO functions. Such a combination must be done very carefully especially when the code has to be portable. (and it is bad to write unportable code...)
    It is certainly best to avoid combining buffered and unbuffered IO on the same file descriptor.

    Buffered IO: fprintf(), fopen(), fclose(), freopen()...

    Unbuffered IO: write(), open(), close(), dup()...

    When you use dup2() to redirect stdout. The function is not aware of the buffer which was filled by fprintf(). So when dup2() closes the old descriptor 1 it does not flush the buffer and the content could be flushed to a different output. In your case 2a it was sent to /dev/null.

    The solution

    In your case it is best to use freopen() instead of dup2(). This solves all your problems:

    1. It flushes the buffers of the original FILE stream. (case 2a)
    2. It sets the buffering mode according to the newly opened file. (case 3)

    Here is the correct implementation of your function:

    void RedirectStdout2File(const char* log_path) {
        if(freopen(log_path, "a+", stdout) == NULL) err(EXIT_FAILURE, NULL);
    }
    

    Unfortunately with buffered IO you cannot directly set permissions of a newly created file. You have to use other calls to change the permissions or you can use unportable glibc extensions. See the fopen() man page.

提交回复
热议问题